Ejemplo n.º 1
0
 /**
  * Replaces any reference to one of the framework's special directories in a path with the directory's actual path
  * and returns the usable path.
  *
  * A framework's directory is referenced in a path by wrapping its ID into double curly braces, as in
  * "{{PHRED_PATH_TO_FRAMEWORK_ROOT}}", optionally with "/" after the reference.
  *
  * @param  string $path The path to the file or directory (can be absolute or relative).
  *
  * @return CUStringObject The usable path.
  */
 public static function frameworkPath($path)
 {
     assert('!isset($path) || is_cstring($path)', vs(isset($this), get_defined_vars()));
     if (!isset($path)) {
         return null;
     }
     // Replace every "{{EXAMPLE_PATH}}" in the path string with the value of "EXAMPLE_PATH" key from $GLOBALS
     // variable if such key exists in the variable.
     $modified = false;
     $path = CRegex::replaceWithCallback($path, "/\\{\\{\\w+\\}\\}/", function ($matches) use(&$modified) {
         $pathVarName = CString::substr($matches[0], 2, CString::length($matches[0]) - 4);
         if (isset($GLOBALS[$pathVarName])) {
             $modified = true;
             return $GLOBALS[$pathVarName] . "/";
         } else {
             assert('false', vs(isset($this), get_defined_vars()));
             return $matches[0];
         }
     });
     if ($modified) {
         $path = CRegex::replace($path, "/\\/{2,}/", "/");
     }
     return $path;
 }
Ejemplo n.º 2
0
 /**
  * Determines if the URL in a specified string is valid.
  *
  * @param  string $url The URL string to be looked into.
  * @param  bool $ignoreProtocolAbsence **OPTIONAL. Default is** `false`. Tells whether the URL in the string may
  * still be considered valid even if it does not indicate any protocol.
  *
  * @return bool `true` if the URL in the string is valid, `false` otherwise.
  */
 public static function isValid($url, $ignoreProtocolAbsence = false)
 {
     assert('is_cstring($url) && is_bool($ignoreProtocolAbsence)', vs(isset($this), get_defined_vars()));
     $parsedUrl = parse_url($url);
     if (!is_cmap($parsedUrl)) {
         return false;
     }
     if ($ignoreProtocolAbsence && !CMap::hasKey($parsedUrl, "scheme")) {
         // No protocol seems to be specified, try with the default one.
         $url = self::DEFAULT_PROTOCOL . "://{$url}";
         $parsedUrl = parse_url($url);
         if (!is_cmap($parsedUrl)) {
             return false;
         }
         if (!CMap::hasKey($parsedUrl, "scheme")) {
             return false;
         }
     }
     if (is_cstring(filter_var($url, FILTER_VALIDATE_URL))) {
         return true;
     } else {
         if (CMap::hasKey($parsedUrl, "host")) {
             // The `filter_var` function could fail to recognize an IPv6 as the URL's host (enclosed in square
             // brackets), so, in case of a valid IPv6 being the host, replace it with an IPv4 and give the URL another
             // try.
             $host = $parsedUrl["host"];
             if (CRegex::find($host, "/^\\[.*\\]\\z/")) {
                 $host = CString::substr($host, 1, CString::length($host) - 2);
                 if (CIp::isValidV6($host)) {
                     // Should not influence the validity if the string is present anywhere else.
                     $url = CString::replace($url, "[{$host}]", "127.0.0.1");
                     if (is_cstring(filter_var($url, FILTER_VALIDATE_URL)) && is_cmap(parse_url($url))) {
                         return true;
                     }
                 }
             }
         }
     }
     return false;
 }
Ejemplo n.º 3
0
 /**
  * Wraps the text in a string to a specified width and returns the new string.
  *
  * @param  string $string The string with the text to be wrapped.
  * @param  int $width The wrapping width, in characters.
  * @param  bitfield $wrappingFlags **OPTIONAL. Default is** `WRAPPING_DEFAULT`. The wrapping option(s). The
  * available options are `WRAPPING_BREAK_SPACELESS_LINES`, `WRAPPING_ALLOW_TRAILING_SPACES`,
  * `WRAPPING_DISALLOW_LEADING_SPACES`, and `WRAPPING_DONT_BREAK_SPACELESS_CJK_ENDING_LINES`
  * (see [Summary](#summary)).
  * @param  string $newline **OPTIONAL. Default is** LF (U+000A). The newline character(s) to be used for making
  * new lines in the process of wrapping.
  *
  * @return string The wrapped text.
  */
 public static function wordWrap($string, $width, $wrappingFlags = self::WRAPPING_DEFAULT, $newline = self::NEWLINE)
 {
     assert('is_cstring($string) && is_int($width) && is_bitfield($wrappingFlags) && is_cstring($newline)', vs(isset($this), get_defined_vars()));
     assert('$width > 0', vs(isset($this), get_defined_vars()));
     // Constant. Newline character that is used by the input string (after newline normalization).
     $normNl = self::NEWLINE;
     // Constant. Determines what characters should be considered spaces.
     // A character in the "Zs" Unicode category, an HT, or a Zero Width Space, except No-break Space and Narrow
     // No-break Space.
     $spaceSubjectRe = "(\\p{Zs}|\\x{0009}|\\x{200B})(?<!\\x{00A0}|\\x{202F})";
     // Break enabling characters.
     // Soft Hyphen or Tibetan Mark Intersyllabic Tsheg.
     $breakAllowCharSubjectRe = "\\x{00AD}|\\x{0F0B}";
     // Retrieve the wrapping options.
     $breakSpacelessLines = CBitField::isBitSet($wrappingFlags, self::WRAPPING_BREAK_SPACELESS_LINES);
     $allowTrailingSpaces = CBitField::isBitSet($wrappingFlags, self::WRAPPING_ALLOW_TRAILING_SPACES);
     $disallowLeadingSpaces = CBitField::isBitSet($wrappingFlags, self::WRAPPING_DISALLOW_LEADING_SPACES);
     $dontBreakSpacelessCjkEndingLines = CBitField::isBitSet($wrappingFlags, self::WRAPPING_DONT_BREAK_SPACELESS_CJK_ENDING_LINES);
     // Normalize newlines in the input string.
     $string = self::normNewlines($string, $normNl);
     $normNlLength = self::length($normNl);
     $newString = "";
     $pos = 0;
     $bytePos = 0;
     $sLength = self::length($string);
     while (true) {
         $numCharsLeft = $sLength - $pos;
         // A portion begins at the very start or right after a newline, either it is native or added. The length of
         // a portion is the wrapping width or less.
         $portionLength = CMathi::min($width, $numCharsLeft);
         $portion = self::substr($string, $pos, $portionLength);
         $portionByteLength = CString::length($portion);
         if ($portionLength == $numCharsLeft) {
             // All done.
             $newString .= $portion;
             break;
         }
         // The starting position of the next portion.
         $nextPos = $pos + $portionLength;
         $nextBytePos = $bytePos + $portionByteLength;
         // Look for the first occurrence of a newline in the portion.
         $nlPos = self::indexOf($portion, $normNl);
         if ($nlPos != -1) {
             // This portion contains a newline, so the next portion is going to start right after this first found
             // newline.
             $subPLength = $nlPos + $normNlLength;
             $subP = self::substr($portion, 0, $subPLength);
             $newString .= $subP;
             $pos += $subPLength;
             $bytePos += CString::length($subP);
             continue;
         }
         // There are no newlines in this portion. Before the next step, make sure that the next portion is not
         // going to start with a newline.
         if ($numCharsLeft - $portionLength >= $normNlLength) {
             $nextPortionBeginning = self::substr($string, $nextPos, $normNlLength);
             if (self::indexOf($nextPortionBeginning, $normNl) == 0) {
                 // The next portion is going to start with a newline, so no need to break this one, regardless of
                 // whether or not it contains any spaces.
                 $newString .= $portion;
                 $pos = $nextPos;
                 $bytePos = $nextBytePos;
                 continue;
             }
         }
         // The next portion is not going to start with a newline. Look for the last occurrence of a space or
         // break-allow character in this portion.
         $lastSubjectBytePos = CRegex::lastIndexOf($portion, "/({$spaceSubjectRe})|({$breakAllowCharSubjectRe})/u", 0, $foundString);
         if ($lastSubjectBytePos != -1) {
             // Add a newline right after this last occurring space or break-allow character.
             $subP = CString::substring($portion, 0, $lastSubjectBytePos + CString::length($foundString));
             $newString .= $subP;
             $newString .= $newline;
             $pos += self::length($subP);
             $bytePos += CString::length($subP);
             continue;
         }
         // There are no spaces or break-allow characters in this portion. Consider adding a newline right after the
         // portion.
         if ($breakSpacelessLines || !$dontBreakSpacelessCjkEndingLines && self::hasCjkChar(self::charAt($portion, $portionLength - 1))) {
             $newString .= $portion;
             $newString .= $newline;
             $pos = $nextPos;
             $bytePos = $nextBytePos;
             continue;
         }
         // There are no spaces or break-allow characters in this portion and it should go adjacent to the upcoming
         // text. Look for the first newline, space, or break-allow character in the upcoming text.
         $nextSubjectBytePos = CRegex::indexOf($string, "/{$normNl}|(({$spaceSubjectRe})|({$breakAllowCharSubjectRe}))(?!{$normNl})/u", $nextBytePos, $foundString);
         if ($nextSubjectBytePos != -1) {
             // Found a newline, space, or a break-allow character, so the next portion is going to start right
             // after it.
             $afterP = CString::substring($string, $nextBytePos, $nextSubjectBytePos + CString::length($foundString));
             $newString .= $portion;
             $newString .= $afterP;
             if (!CString::equals($foundString, $normNl)) {
                 // It is a space or break-allow character that was found, so add a newline after it.
                 $newString .= $newline;
             }
             $pos += $portionLength + self::length($afterP);
             $bytePos += $portionByteLength + CString::length($afterP);
             continue;
         }
         // There are no spaces, newlines, or break-allow characters in the upcoming text. Finalize according to the
         // breaking options.
         if (!$breakSpacelessLines) {
             $newString .= $portion;
             $newString .= self::substr($string, $nextPos);
         } else {
             $newString .= $portion;
             $newString .= $newline;
             $pos = $nextPos;
             while (true) {
                 $numCharsLeft = $sLength - $pos;
                 $portionLength = CMathi::min($width, $numCharsLeft);
                 $newString .= self::substr($string, $pos, $portionLength);
                 if ($portionLength == $numCharsLeft) {
                     break;
                 }
                 $newString .= $newline;
                 $pos += $portionLength;
             }
         }
         break;
     }
     if (!$allowTrailingSpaces) {
         // Remove trailing spaces.
         $newString = CRegex::remove($newString, "/({$spaceSubjectRe})+(?={$normNl}|\\z)/u");
     }
     if ($disallowLeadingSpaces) {
         // Remove leading spaces.
         $newString = CRegex::remove($newString, "/(?<={$normNl}|^)({$spaceSubjectRe})+/u");
     }
     return $newString;
 }
Ejemplo n.º 4
0
 /**
  * @ignore
  */
 public static function onThirdPartyUpdateByPackageManager()
 {
     if (!self::isInCliMode()) {
         // This method can be run in CLI mode only.
         assert('false', vs(isset($this), get_defined_vars()));
     }
     $timeoutPause = new CTimeoutPause();
     CShell::speak("Processing third-party components ...");
     $tpDps = CFile::listDirectories(CFilePath::absolute($GLOBALS["PHRED_PATH_TO_THIRD_PARTY"]));
     $ignorePackages = CConfiguration::option("upd.thirdPartyOopWrappingIgnorePackages");
     $ignorePackagesL2 = CArray::filter($ignorePackages, function ($package) {
         return CString::find($package, "/");
     });
     $newTpDps = CArray::make();
     $len = CArray::length($tpDps);
     for ($i = 0; $i < $len; $i++) {
         $tpDp = $tpDps[$i];
         $dirName = CFilePath::name($tpDp);
         if (!CArray::find($ignorePackages, $dirName)) {
             $dpHasL2DirsToIgnore = CArray::find($ignorePackagesL2, $dirName, function ($packageL2, $dirName) {
                 return CString::equals(CFilePath::directory($packageL2), $dirName);
             });
             if (!$dpHasL2DirsToIgnore) {
                 CArray::push($newTpDps, $tpDp);
             } else {
                 $tpSubDps = CFile::listDirectories($tpDp);
                 $tpSubDps = CArray::filter($tpSubDps, function ($subDp) use($ignorePackagesL2) {
                     return !CArray::find($ignorePackagesL2, $subDp, function ($packageL2, $subDp) {
                         return CString::endsWith($subDp, $packageL2);
                     });
                 });
                 CArray::pushArray($newTpDps, $tpSubDps);
             }
         }
     }
     $tpDps = $newTpDps;
     $wrapProtectedMethods = CConfiguration::option("upd.thirdPartyOopWrappingInProtectedMethods");
     $wrapPrivateMethods = CConfiguration::option("upd.thirdPartyOopWrappingInPrivateMethods");
     static $s_stdPhpTag = "<?php";
     static $s_progressResolution = 0.05;
     $prevProgressDivR = 0;
     $tpDpsLen = CArray::length($tpDps);
     for ($i0 = 0; $i0 < $tpDpsLen; $i0++) {
         $tpFps = CFile::reFindFilesRecursive($tpDps[$i0], "/\\.php\\d?\\z/");
         $tpFpsLen = CArray::length($tpFps);
         for ($i1 = 0; $i1 < $tpFpsLen; $i1++) {
             $fileCode = CFile::read($tpFps[$i1]);
             if (!CString::find($fileCode, self::$ms_thirdPartyAlreadyOopWrappedMark)) {
                 $parser = new PhpParser\Parser(new PhpParser\Lexer());
                 try {
                     // Parse the code.
                     $statements = $parser->parse($fileCode);
                     // Wrap the code into OOP.
                     $traverser = new PhpParser\NodeTraverser();
                     $mainVisitor = new CMainVisitor($wrapProtectedMethods, $wrapPrivateMethods);
                     $traverser->addVisitor($mainVisitor);
                     $statements = $traverser->traverse($statements);
                     $wrappedCode = (new PhpParser\PrettyPrinter\Standard())->prettyPrint($statements);
                     $phpTagPos = CString::indexOf($wrappedCode, $s_stdPhpTag);
                     if ($phpTagPos == -1) {
                         $wrappedCode = "{$s_stdPhpTag}\n\n{$wrappedCode}";
                         $phpTagPos = 0;
                     }
                     $wrappedCode = CString::insert($wrappedCode, $phpTagPos + CString::length($s_stdPhpTag), "\n\n" . self::$ms_thirdPartyAlreadyOopWrappedMark);
                     // Save.
                     CFile::write($tpFps[$i1], $wrappedCode);
                 } catch (PhpParser\Error $parserError) {
                     CShell::say("\nPhpParser: " . $tpFps[$i1] . ", at line " . $parserError->getRawLine() . ": " . $parserError->getRawMessage());
                 }
             }
             $progress = (double) ($i0 / $tpDpsLen + 1 / $tpDpsLen * $i1 / $tpFpsLen);
             $progressDivR = CMathi::floor($progress / $s_progressResolution);
             if ($progressDivR != $prevProgressDivR) {
                 $perc = CMathi::round($progressDivR * $s_progressResolution * 100);
                 CShell::speak("{$perc}%");
             }
             $prevProgressDivR = $progressDivR;
         }
     }
     CShell::speak("100%");
     CShell::say("Done.");
     $timeoutPause->end();
 }
Ejemplo n.º 5
0
 /**
  * @ignore
  */
 public function headerFunction($curl, $headerLine)
 {
     $ret = CString::length($headerLine);
     $foundGroups;
     if (CRegex::findGroups($headerLine, "/^\\s*(.+?)\\h*:\\h*(.*?)\\s*\\z/", $foundGroups)) {
         $this->addHeaderWithoutOverriding($this->m_responseHeaders, $foundGroups[0], $foundGroups[1]);
     }
     return $ret;
 }