예제 #1
0
 /**
  * Get the string wrapper supporting UTF-8 character encoding
  *
  * @return StringWrapperInterface
  */
 public function getUtf8StringWrapper()
 {
     if (!$this->utf8StringWrapper) {
         $this->utf8StringWrapper = StringUtils::getWrapper('UTF-8');
     }
     return $this->utf8StringWrapper;
 }
예제 #2
0
 /**
  * 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;
 }
 public function setUp()
 {
     if (!StringUtils::hasPcreUnicodeSupport()) {
         return $this->markTestSkipped('PCRE is not compiled with Unicode support');
     }
     $this->reflection = new ReflectionProperty('Zend\\Stdlib\\StringUtils', 'hasPcreUnicodeSupport');
     $this->reflection->setAccessible(true);
     $this->reflection->setValue(false);
 }
예제 #4
0
 /**
  * Validator callback for new group name - check length if necessary
  *
  * @param string $value
  * @param array $context
  * @param integer $min
  * @param integer $max
  * @return bool
  * @internal
  */
 public function validateLength($value, $context, $min, $max)
 {
     if ($context['Where'] == 'new') {
         $length = \Zend\Stdlib\StringUtils::getWrapper('UTF-8')->strlen($value);
         $result = ($length >= $min and $length <= $max);
     } else {
         $result = true;
         // Field is ignored for existing groups
     }
     return $result;
 }
예제 #5
0
 /**
  * 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);
 }
예제 #6
0
파일: String.php 프로젝트: Andyyang1981/pi
 /**
  * Get string wrapper
  *
  * @param string $encoding
  *
  * @return StringWrapperInterface
  */
 public function getWrapper($encoding = '')
 {
     $encoding = strtoupper($encoding ?: Pi::config('charset'));
     if (!isset($this->stringWrapper[$encoding])) {
         try {
             $stringWrapper = StringUtils::getWrapper(Pi::config('charset'));
         } catch (\Exception $e) {
             $stringWrapper = false;
         }
         $this->stringWrapper[$encoding] = $stringWrapper;
     }
     return $this->stringWrapper[$encoding];
 }
예제 #7
0
 /**
  * Defined by Zend\Filter\FilterInterface
  *
  * Returns the string $value, removing all but digit characters
  *
  * @param  string $value
  * @return string
  */
 public function filter($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);
 }
예제 #8
0
 /**
  * Defined by Zend\Filter\Filter
  *
  * @param  string|array $value
  * @return string|array
  */
 public function filter($value)
 {
     if (!is_scalar($value) && !is_array($value)) {
         return $value;
     }
     $value = parent::filter($value);
     $lowerCaseFirst = 'lcfirst';
     if (StringUtils::hasPcreUnicodeSupport() && extension_loaded('mbstring')) {
         $lowerCaseFirst = function ($value) {
             if (0 === mb_strlen($value)) {
                 return $value;
             }
             return mb_strtolower(mb_substr($value, 0, 1)) . mb_substr($value, 1);
         };
     }
     return is_array($value) ? array_map($lowerCaseFirst, $value) : call_user_func($lowerCaseFirst, $value);
 }
예제 #9
0
 /**
  * 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);
 }
예제 #10
0
 protected function getKeywords($string)
 {
     $innerPattern = StringUtils::hasPcreUnicodeSupport() ? '[^\\p{L}]' : '[^a-z0-9ßäöü ]';
     $pattern = '~' . $innerPattern . '~isu';
     $stripPattern = '~^' . $innerPattern . '+|' . $innerPattern . '+$~isu';
     $parts = array();
     $textParts = explode(' ', $string);
     foreach ($textParts as $part) {
         $part = strtolower(trim($part));
         $part = preg_replace($stripPattern, '', $part);
         if ('' == $part) {
             continue;
         }
         $parts[] = $part;
         $tmpPart = preg_replace($pattern, ' ', $part);
         if ($part != $tmpPart) {
             $tmpParts = explode(' ', $tmpPart);
             $tmpParts = array_filter($tmpParts);
             $parts = array_merge($parts, $tmpParts);
         }
     }
     return $parts;
 }
예제 #11
0
 /**
  * Defined by Interface
  *
  * Returns true if and only if the $value is a valid hostname with respect to the current allow option
  *
  * @param  string $value
  * @return bool
  */
 public function isValid($value)
 {
     if (!is_string($value)) {
         $this->error(self::INVALID);
         return false;
     }
     $this->setValue($value);
     // Check input against IP address schema
     if ((preg_match('/^[0-9.]*$/', $value) && strpos($value, '.') !== false || preg_match('/^[0-9a-f:.]*$/i', $value) && strpos($value, ':') !== false) && $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value)) {
         if (!($this->getAllow() & self::ALLOW_IP)) {
             $this->error(self::IP_ADDRESS_NOT_ALLOWED);
             return false;
         }
         return true;
     }
     // Local hostnames are allowed to be partial (ending '.')
     if ($this->getAllow() & self::ALLOW_LOCAL) {
         if (substr($value, -1) === '.') {
             $value = substr($value, 0, -1);
             if (substr($value, -1) === '.') {
                 // Empty hostnames (ending '..') are not allowed
                 $this->error(self::INVALID_LOCAL_NAME);
                 return false;
             }
         }
     }
     $domainParts = explode('.', $value);
     // Prevent partial IP V4 addresses (ending '.')
     if (count($domainParts) == 4 && preg_match('/^[0-9.a-e:.]*$/i', $value) && $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value)) {
         $this->error(self::INVALID_LOCAL_NAME);
     }
     $utf8StrWrapper = StringUtils::getWrapper('UTF-8');
     // Check input against DNS hostname schema
     if (count($domainParts) > 1 && $utf8StrWrapper->strlen($value) >= 4 && $utf8StrWrapper->strlen($value) <= 254) {
         $status = false;
         do {
             // First check TLD
             $matches = [];
             if (preg_match('/([^.]{2,63})$/u', end($domainParts), $matches) || array_key_exists(end($domainParts), $this->validIdns)) {
                 reset($domainParts);
                 // Hostname characters are: *(label dot)(label dot label); max 254 chars
                 // label: id-prefix [*ldh{61} id-prefix]; max 63 chars
                 // id-prefix: alpha / digit
                 // ldh: alpha / digit / dash
                 // Match TLD against known list
                 $this->tld = strtoupper($matches[1]);
                 if ($this->getTldCheck()) {
                     if (!in_array(strtolower($this->tld), $this->validTlds) && !in_array($this->tld, $this->validTlds)) {
                         $this->error(self::UNKNOWN_TLD);
                         $status = false;
                         break;
                     }
                     // We have already validated that the TLD is fine. We don't want it to go through the below
                     // checks as new UTF-8 TLDs will incorrectly fail if there is no IDN regex for it.
                     array_pop($domainParts);
                 }
                 /**
                  * Match against IDN hostnames
                  * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames
                  *
                  * @see Hostname\Interface
                  */
                 $regexChars = [0 => '/^[a-z0-9\\x2d]{1,63}$/i'];
                 if ($this->getIdnCheck() && isset($this->validIdns[$this->tld])) {
                     if (is_string($this->validIdns[$this->tld])) {
                         $regexChars += (include __DIR__ . '/' . $this->validIdns[$this->tld]);
                     } else {
                         $regexChars += $this->validIdns[$this->tld];
                     }
                 }
                 // Check each hostname part
                 $check = 0;
                 foreach ($domainParts as $domainPart) {
                     // Decode Punycode domain names to IDN
                     if (strpos($domainPart, 'xn--') === 0) {
                         $domainPart = $this->decodePunycode(substr($domainPart, 4));
                         if ($domainPart === false) {
                             return false;
                         }
                     }
                     // Check dash (-) does not start, end or appear in 3rd and 4th positions
                     if ($utf8StrWrapper->strpos($domainPart, '-') === 0 || $utf8StrWrapper->strlen($domainPart) > 2 && $utf8StrWrapper->strpos($domainPart, '-', 2) == 2 && $utf8StrWrapper->strpos($domainPart, '-', 3) == 3 || $utf8StrWrapper->strpos($domainPart, '-') === $utf8StrWrapper->strlen($domainPart) - 1) {
                         $this->error(self::INVALID_DASH);
                         $status = false;
                         break 2;
                     }
                     // Check each domain part
                     $checked = false;
                     foreach ($regexChars as $regexKey => $regexChar) {
                         $status = preg_match($regexChar, $domainPart);
                         if ($status > 0) {
                             $length = 63;
                             if (array_key_exists($this->tld, $this->idnLength) && array_key_exists($regexKey, $this->idnLength[$this->tld])) {
                                 $length = $this->idnLength[$this->tld];
                             }
                             if ($utf8StrWrapper->strlen($domainPart) > $length) {
                                 $this->error(self::INVALID_HOSTNAME);
                                 $status = false;
                             } else {
                                 $checked = true;
                                 break;
                             }
                         }
                     }
                     if ($checked) {
                         ++$check;
                     }
                 }
                 // If one of the labels doesn't match, the hostname is invalid
                 if ($check !== count($domainParts)) {
                     $this->error(self::INVALID_HOSTNAME_SCHEMA);
                     $status = false;
                 }
             } else {
                 // Hostname not long enough
                 $this->error(self::UNDECIPHERABLE_TLD);
                 $status = false;
             }
         } while (false);
         // If the input passes as an Internet domain name, and domain names are allowed, then the hostname
         // passes validation
         if ($status && $this->getAllow() & self::ALLOW_DNS) {
             return true;
         }
     } elseif ($this->getAllow() & self::ALLOW_DNS) {
         $this->error(self::INVALID_HOSTNAME);
     }
     // Check for URI Syntax (RFC3986)
     if ($this->getAllow() & self::ALLOW_URI) {
         if (preg_match("/^([a-zA-Z0-9-._~!\$&\\'()*+,;=]|%[[:xdigit:]]{2}){1,254}\$/i", $value)) {
             return true;
         }
         $this->error(self::INVALID_URI);
     }
     // Check input against local network name schema; last chance to pass validation
     $regexLocal = '/^(([a-zA-Z0-9\\x2d]{1,63}\\x2e)*[a-zA-Z0-9\\x2d]{1,63}[\\x2e]{0,1}){1,254}$/';
     $status = preg_match($regexLocal, $value);
     // If the input passes as a local network name, and local network names are allowed, then the
     // hostname passes validation
     $allowLocal = $this->getAllow() & self::ALLOW_LOCAL;
     if ($status && $allowLocal) {
         return true;
     }
     // If the input does not pass as a local network name, add a message
     if (!$status) {
         $this->error(self::INVALID_LOCAL_NAME);
     }
     // If local network names are not allowed, add a message
     if ($status && !$allowLocal) {
         $this->error(self::LOCAL_NAME_NOT_ALLOWED);
     }
     return false;
 }
예제 #12
0
 public function importCsv($csv, User $user, $bankCode)
 {
     if ($csv['error'] != 0) {
         throw new \InvalidArgumentException('System has errors with uploaded file');
     }
     if (!$user) {
         return;
     }
     $counts = array(0, 0);
     if (($handle = fopen($csv['tmp_name'], 'r')) !== false) {
         // 			fgets($handle, 4096);
         $data = fgets($handle, 4096);
         $delimiter = ',';
         if (count(explode(';', $data)) > 8) {
             $delimiter = ';';
         }
         rewind($handle);
         $data = fgetcsv($handle, 4096, $delimiter);
         if (in_array($data[0], array('Konto', 'Kliendi konto'))) {
             $data = fgetcsv($handle, 4096, $delimiter);
         }
         rewind($handle);
         while (($data = fgetcsv($handle, 4096, $delimiter)) !== false) {
             if (in_array($data[0], array('Konto', 'Kliendi konto'))) {
                 continue;
             }
             if ($bankCode == BankTransaction::BANK_KREDIIDIPANK) {
                 //valjavote.csv
                 $name = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[14]));
                 $referenceNumber = trim($data[22]);
                 $sum = str_replace(',', '.', trim($data[3]));
                 $paymentDate = \DateTime::createFromFormat('d.m.Y', $data[0]);
                 $description = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[21]));
                 $archiveSign = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[1]));
                 $payerIban = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[16]));
             } elseif ($bankCode == BankTransaction::BANK_SEB) {
                 $name = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[4]));
                 $referenceNumber = trim($data[9]);
                 $sum = str_replace(',', '.', (trim($data[7] == 'D') ? -1 : 1) * trim(str_replace(',', '.', $data[8])));
                 $paymentDate = \DateTime::createFromFormat('d.m.Y', $data[2]);
                 $description = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[11]));
                 $archiveSign = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[10]));
                 $payerIban = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[3]));
             } elseif ($bankCode == BankTransaction::BANK_SWED) {
                 //toimingud.csv
                 $name = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[4]));
                 $referenceNumber = trim($data[9]);
                 $sum = str_replace(',', '.', trim($data[8]));
                 $paymentDate = \DateTime::createFromFormat('d-m-Y', $data[2]);
                 $description = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[11]));
                 $archiveSign = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[10]));
                 $payerIban = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[3]));
             } elseif ($bankCode == BankTransaction::BANK_NORDEA) {
                 $name = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[4]));
                 $referenceNumber = trim($data[7]);
                 $sum = str_replace(',', '.', (trim($data[5] == 'D') ? -1 : 1) * trim(str_replace(',', '.', $data[6])));
                 $paymentDate = \DateTime::createFromFormat('d.m.Y', $data[2]);
                 $description = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[9]));
                 $archiveSign = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[8]));
                 $payerIban = StringUtils::getWrapper('ISO-8859-1', 'UTF-8')->convert(trim($data[3]));
             }
             if ($name == null || $paymentDate === false) {
                 continue;
             }
             $paymentDate->setTime(0, 0, 0);
             if ($archiveSign !== null && $archiveSign !== '') {
                 $transaction = $this->entityManager->getRepository(BankTransaction::getClass())->findOneBy(array('name' => $name, 'referenceNumber' => $referenceNumber, 'sum' => $sum, 'paymentDate' => $paymentDate, 'description' => $description, 'archiveSign' => $archiveSign));
                 if ($transaction != null) {
                     continue;
                 }
             }
             $transaction = new BankTransaction();
             $transaction->setName($name);
             $transaction->setReferenceNumber($referenceNumber);
             $transaction->setSum($sum);
             $transaction->setType($sum < 0 ? BankTransaction::TYPE_OUTGOING : BankTransaction::TYPE_INCOMING);
             $transaction->setPaymentDate($paymentDate);
             $transaction->setDescription($description);
             $transaction->setArchiveSign($archiveSign);
             $transaction->setPayerIban($payerIban);
             $transaction->setPaymentType(BankTransaction::PAYMENT_TYPE_TRANSFER);
             $transaction->setUser($user);
             $this->saveTransaction($transaction);
             if ($sum > 0) {
                 $counts[1]++;
                 $this->autoAssociateIncoming($transaction);
             } else {
                 $counts[0]++;
             }
         }
         fclose($handle);
     }
     return $counts;
 }
예제 #13
0
 /**
  * Encode a text to match console encoding
  *
  * @param  string $text
  * @return string the encoding text
  */
 public function encodeText($text)
 {
     if ($this->isUtf8()) {
         if (StringUtils::isValidUtf8($text)) {
             return $text;
         }
         return utf8_encode($text);
     }
     if (StringUtils::isValidUtf8($text)) {
         return utf8_decode($text);
     }
     return $text;
 }
 /**
  * Pad a string to a certain length with another string
  *
  * @param  string  $input
  * @param  integer $padLength
  * @param  string  $padString
  * @param  integer $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;
 }
예제 #15
0
 /**
  * Get all the regex components
  *
  * @return array
  */
 public function getRegexComponents()
 {
     if ($this->regexComponents == null) {
         $this->regexComponents[self::REGEX_NUMBERS] = '0-9';
         $this->regexComponents[self::REGEX_FLAGS] = '';
         if (StringUtils::hasPcreUnicodeSupport()) {
             $this->regexComponents[self::REGEX_NUMBERS] = '\\p{N}';
             $this->regexComponents[self::REGEX_FLAGS] .= 'u';
         }
     }
     return $this->regexComponents;
 }
예제 #16
0
 /**
  * Validator callback
  *
  * @internal
  * @param string $value
  * @param array $context
  * @param string $type Field datatype
  * @return bool TRUE if $value is valid for given type
  */
 public function validateField($value, $context, $type)
 {
     switch ($type) {
         case 'text':
             $result = \Zend\Stdlib\StringUtils::getWrapper('UTF-8')->strlen($value) <= 255;
             break;
         case 'integer':
         case 'float':
         case 'date':
             $result = $this->validateType($value, $context, $type);
             break;
         default:
             $result = true;
     }
     return $result;
 }
예제 #17
0
 /**
  * Sets a new encoding to use
  *
  * @param string $encoding
  * @return StringLength
  * @throws Exception\InvalidArgumentException
  */
 public function setEncoding($encoding)
 {
     $this->stringWrapper = StringUtils::getWrapper($encoding);
     $this->options['encoding'] = $encoding;
     return $this;
 }
예제 #18
0
 /**
  * Returns true if and only if $value is a floating-point value. Uses the formal definition of a float as described
  * in the PHP manual: {@link http://www.php.net/float}
  *
  * @param  string $value
  * @return bool
  * @throws Exception\InvalidArgumentException
  */
 public function isValid($value)
 {
     if (!is_scalar($value) || is_bool($value)) {
         $this->error(self::INVALID);
         return false;
     }
     $this->setValue($value);
     if (is_float($value) || is_int($value)) {
         return true;
     }
     // Need to check if this is scientific formatted string. If not, switch to decimal.
     $formatter = new NumberFormatter($this->getLocale(), NumberFormatter::SCIENTIFIC);
     if (intl_is_failure($formatter->getErrorCode())) {
         throw new Exception\InvalidArgumentException($formatter->getErrorMessage());
     }
     if (StringUtils::hasPcreUnicodeSupport()) {
         $exponentialSymbols = '[Ee' . $formatter->getSymbol(NumberFormatter::EXPONENTIAL_SYMBOL) . ']+';
         $search = '/' . $exponentialSymbols . '/u';
     } else {
         $exponentialSymbols = '[Ee]';
         $search = '/' . $exponentialSymbols . '/';
     }
     if (!preg_match($search, $value)) {
         $formatter = new NumberFormatter($this->getLocale(), NumberFormatter::DECIMAL);
     }
     /**
      * @desc There are seperator "look-alikes" for decimal and group seperators that are more commonly used than the
      *       official unicode chracter. We need to replace those with the real thing - or remove it.
      */
     $groupSeparator = $formatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
     $decSeparator = $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
     //NO-BREAK SPACE and ARABIC THOUSANDS SEPARATOR
     if ($groupSeparator == " ") {
         $value = str_replace(' ', $groupSeparator, $value);
     } elseif ($groupSeparator == "٬") {
         //NumberFormatter doesn't have grouping at all for Arabic-Indic
         $value = str_replace(array('\'', $groupSeparator), '', $value);
     }
     //ARABIC DECIMAL SEPARATOR
     if ($decSeparator == "٫") {
         $value = str_replace(',', $decSeparator, $value);
     }
     $groupSeparatorPosition = $this->wrapper->strpos($value, $groupSeparator);
     $decSeparatorPosition = $this->wrapper->strpos($value, $decSeparator);
     //We have seperators, and they are flipped. i.e. 2.000,000 for en-US
     if ($groupSeparatorPosition && $decSeparatorPosition && $groupSeparatorPosition > $decSeparatorPosition) {
         return false;
     }
     //If we have Unicode support, we can use the real graphemes, otherwise, just the ASCII characters
     $decimal = '[' . preg_quote($decSeparator, '/') . ']';
     $prefix = '[+-]';
     $exp = $exponentialSymbols;
     $numberRange = '0-9';
     $useUnicode = '';
     $suffix = '';
     if (StringUtils::hasPcreUnicodeSupport()) {
         $prefix = '[' . preg_quote($formatter->getTextAttribute(NumberFormatter::POSITIVE_PREFIX) . $formatter->getTextAttribute(NumberFormatter::NEGATIVE_PREFIX) . $formatter->getSymbol(NumberFormatter::PLUS_SIGN_SYMBOL) . $formatter->getSymbol(NumberFormatter::MINUS_SIGN_SYMBOL), '/') . ']{0,3}';
         $suffix = $formatter->getTextAttribute(NumberFormatter::NEGATIVE_SUFFIX) ? '[' . preg_quote($formatter->getTextAttribute(NumberFormatter::POSITIVE_SUFFIX) . $formatter->getTextAttribute(NumberFormatter::NEGATIVE_SUFFIX) . $formatter->getSymbol(NumberFormatter::PLUS_SIGN_SYMBOL) . $formatter->getSymbol(NumberFormatter::MINUS_SIGN_SYMBOL), '/') . ']{0,3}' : '';
         $numberRange = '\\p{N}';
         $useUnicode = 'u';
     }
     /**
      * @desc Match against the formal definition of a float. The
      *       exponential number check is modified for RTL non-Latin number
      *       systems (Arabic-Indic numbering). I'm also switching out the period
      *       for the decimal separator. The formal definition leaves out +- from
      *       the integer and decimal notations so add that.  This also checks
      *       that a grouping sperator is not in the last GROUPING_SIZE graphemes
      *       of the string - i.e. 10,6 is not valid for en-US.
      * @see http://www.php.net/float
      */
     $lnum = '[' . $numberRange . ']+';
     $dnum = '(([' . $numberRange . ']*' . $decimal . $lnum . ')|(' . $lnum . $decimal . '[' . $numberRange . ']*))';
     $expDnum = '((' . $prefix . '((' . $lnum . '|' . $dnum . ')' . $exp . $prefix . $lnum . ')' . $suffix . ')|' . '(' . $suffix . '(' . $lnum . $prefix . $exp . '(' . $dnum . '|' . $lnum . '))' . $prefix . '))';
     // LEFT-TO-RIGHT MARK (U+200E) is messing up everything for the handful
     // of locales that have it
     $lnumSearch = str_replace("‎", '', '/^' . $prefix . $lnum . $suffix . '$/' . $useUnicode);
     $dnumSearch = str_replace("‎", '', '/^' . $prefix . $dnum . $suffix . '$/' . $useUnicode);
     $expDnumSearch = str_replace("‎", '', '/^' . $expDnum . '$/' . $useUnicode);
     $value = str_replace("‎", '', $value);
     $unGroupedValue = str_replace($groupSeparator, '', $value);
     // No strrpos() in wrappers yet. ICU 4.x doesn't have grouping size for
     // everything. ICU 52 has 3 for ALL locales.
     $groupSize = $formatter->getAttribute(NumberFormatter::GROUPING_SIZE) ? $formatter->getAttribute(NumberFormatter::GROUPING_SIZE) : 3;
     $lastStringGroup = $this->wrapper->substr($value, -$groupSize);
     if ((preg_match($lnumSearch, $unGroupedValue) || preg_match($dnumSearch, $unGroupedValue) || preg_match($expDnumSearch, $unGroupedValue)) && false === $this->wrapper->strpos($lastStringGroup, $groupSeparator)) {
         return true;
     }
     return false;
 }
예제 #19
0
 public function __construct(Console $console, $displayData = false)
 {
     $this->console = $console;
     $this->stringUtils = StringUtils::getWrapper();
     $this->displayData = $displayData;
 }
예제 #20
0
 /**
  * Returns true if and only if $value is a number correctly expressed with the scientific notation
  *
  * Note that it can only validate string inputs.
  *
  * @param mixed $value
  * @return bool
  */
 public function isValid($value)
 {
     if (!is_scalar($value) || is_bool($value)) {
         $this->error(self::INVALID_INPUT);
         return false;
     }
     $formatter = new \NumberFormatter($this->getLocale(), \NumberFormatter::SCIENTIFIC);
     $flags = 'i';
     $expSymbol = 'E';
     if (StringUtils::hasPcreUnicodeSupport()) {
         $expSymbol = preg_quote($formatter->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL));
         $flags .= 'u';
     }
     // Check that exponentation symbol is present
     $search = str_replace("‎", '', sprintf('/%s/%s', $expSymbol, $flags));
     $value = str_replace("‎", '', $value);
     if (!preg_match($search, $value)) {
         $this->error(self::NOT_SCIENTIFIC);
         return false;
     }
     // Check that the number expressed in scientific notation is a valid number
     $float = new IsFloat(['locale' => $this->getLocale()]);
     if (!$float->isValid($value)) {
         $this->error(self::NOT_NUMBER);
         return false;
     }
     return true;
 }
예제 #21
0
 /**
  * Write a box at the specified coordinates.
  * If X or Y coordinate value is negative, it will be calculated as the distance from far right or bottom edge
  * of the console (respectively).
  *
  * @param int      $x1           Top-left corner X coordinate (column)
  * @param int      $y1           Top-left corner Y coordinate (row)
  * @param int      $x2           Bottom-right corner X coordinate (column)
  * @param int      $y2           Bottom-right corner Y coordinate (row)
  * @param int      $lineStyle    (optional) Box border style.
  * @param int      $fillStyle    (optional) Box fill style or a single character to fill it with.
  * @param int      $color        (optional) Foreground color
  * @param int      $bgColor      (optional) Background color
  * @param null|int $fillColor    (optional) Foreground color of box fill
  * @param null|int $fillBgColor  (optional) Background color of box fill
  * @throws Exception\BadMethodCallException if coordinates are invalid
  */
 public function writeBox($x1, $y1, $x2, $y2, $lineStyle = self::LINE_SINGLE, $fillStyle = self::FILL_NONE, $color = null, $bgColor = null, $fillColor = null, $fillBgColor = null)
 {
     // Sanitize coordinates
     $x1 = (int) $x1;
     $y1 = (int) $y1;
     $x2 = (int) $x2;
     $y2 = (int) $y2;
     // Translate negative coordinates
     if ($x2 < 0) {
         $x2 = $this->getWidth() - $x2;
     }
     if ($y2 < 0) {
         $y2 = $this->getHeight() - $y2;
     }
     // Validate coordinates
     if ($x1 < 0 || $y1 < 0 || $x2 < $x1 || $y2 < $y1) {
         throw new Exception\BadMethodCallException('Supplied X,Y coordinates are invalid.');
     }
     // Determine charset and dimensions
     $charset = $this->getCharset();
     $width = $x2 - $x1 + 1;
     $height = $y2 - $y1 + 1;
     if ($width <= 2) {
         $lineStyle = static::LINE_NONE;
     }
     // Activate line drawing
     $this->write($charset::ACTIVATE);
     // Draw horizontal lines
     if ($lineStyle !== static::LINE_NONE) {
         switch ($lineStyle) {
             case static::LINE_SINGLE:
                 $lineChar = $charset::LINE_SINGLE_EW;
                 break;
             case static::LINE_DOUBLE:
                 $lineChar = $charset::LINE_DOUBLE_EW;
                 break;
             case static::LINE_BLOCK:
             default:
                 $lineChar = $charset::LINE_BLOCK_EW;
                 break;
         }
         $this->setPos($x1 + 1, $y1);
         $this->write(str_repeat($lineChar, $width - 2), $color, $bgColor);
         $this->setPos($x1 + 1, $y2);
         $this->write(str_repeat($lineChar, $width - 2), $color, $bgColor);
     }
     // Draw vertical lines and fill
     if (is_numeric($fillStyle) && $fillStyle !== static::FILL_NONE) {
         switch ($fillStyle) {
             case static::FILL_SHADE_LIGHT:
                 $fillChar = $charset::SHADE_LIGHT;
                 break;
             case static::FILL_SHADE_MEDIUM:
                 $fillChar = $charset::SHADE_MEDIUM;
                 break;
             case static::FILL_SHADE_DARK:
                 $fillChar = $charset::SHADE_DARK;
                 break;
             case static::FILL_BLOCK:
             default:
                 $fillChar = $charset::BLOCK;
                 break;
         }
     } elseif ($fillStyle) {
         $fillChar = StringUtils::getWrapper()->substr($fillStyle, 0, 1);
     } else {
         $fillChar = ' ';
     }
     if ($lineStyle === static::LINE_NONE) {
         for ($y = $y1; $y <= $y2; $y++) {
             $this->setPos($x1, $y);
             $this->write(str_repeat($fillChar, $width), $fillColor, $fillBgColor);
         }
     } else {
         switch ($lineStyle) {
             case static::LINE_DOUBLE:
                 $lineChar = $charset::LINE_DOUBLE_NS;
                 break;
             case static::LINE_BLOCK:
                 $lineChar = $charset::LINE_BLOCK_NS;
                 break;
             case static::LINE_SINGLE:
             default:
                 $lineChar = $charset::LINE_SINGLE_NS;
                 break;
         }
         for ($y = $y1 + 1; $y < $y2; $y++) {
             $this->setPos($x1, $y);
             $this->write($lineChar, $color, $bgColor);
             $this->write(str_repeat($fillChar, $width - 2), $fillColor, $fillBgColor);
             $this->write($lineChar, $color, $bgColor);
         }
     }
     // Draw corners
     if ($lineStyle !== static::LINE_NONE) {
         if ($color !== null) {
             $this->setColor($color);
         }
         if ($bgColor !== null) {
             $this->setBgColor($bgColor);
         }
         if ($lineStyle === static::LINE_SINGLE) {
             $this->writeAt($charset::LINE_SINGLE_NW, $x1, $y1);
             $this->writeAt($charset::LINE_SINGLE_NE, $x2, $y1);
             $this->writeAt($charset::LINE_SINGLE_SE, $x2, $y2);
             $this->writeAt($charset::LINE_SINGLE_SW, $x1, $y2);
         } elseif ($lineStyle === static::LINE_DOUBLE) {
             $this->writeAt($charset::LINE_DOUBLE_NW, $x1, $y1);
             $this->writeAt($charset::LINE_DOUBLE_NE, $x2, $y1);
             $this->writeAt($charset::LINE_DOUBLE_SE, $x2, $y2);
             $this->writeAt($charset::LINE_DOUBLE_SW, $x1, $y2);
         } elseif ($lineStyle === static::LINE_BLOCK) {
             $this->writeAt($charset::LINE_BLOCK_NW, $x1, $y1);
             $this->writeAt($charset::LINE_BLOCK_NE, $x2, $y1);
             $this->writeAt($charset::LINE_BLOCK_SE, $x2, $y2);
             $this->writeAt($charset::LINE_BLOCK_SW, $x1, $y2);
         }
     }
     // Deactivate line drawing and reset colors
     $this->write($charset::DEACTIVATE);
     $this->resetColor();
 }
예제 #22
0
 /**
  * Render the column width the given column width
  *
  * @param  int $columnWidth The width of the column
  * @param  int $padding     The padding for the column
  * @throws Exception\InvalidArgumentException When $columnWidth is lower than 1
  * @throws Exception\OutOfBoundsException When padding is greater than columnWidth
  * @return string
  */
 public function render($columnWidth, $padding = 0)
 {
     if (is_int($columnWidth) === false or $columnWidth < 1) {
         throw new Exception\InvalidArgumentException('$columnWidth must be an integer and greater than 0');
     }
     $columnWidth -= $padding * 2;
     if ($columnWidth < 1) {
         throw new Exception\OutOfBoundsException('Padding (' . $padding . ') is greater than column width');
     }
     switch ($this->align) {
         case self::ALIGN_LEFT:
             $padMode = STR_PAD_RIGHT;
             break;
         case self::ALIGN_CENTER:
             $padMode = STR_PAD_BOTH;
             break;
         case self::ALIGN_RIGHT:
             $padMode = STR_PAD_LEFT;
             break;
         default:
             // This can never happen, but the CS tells I have to have it ...
             break;
     }
     $outputCharset = Table::getOutputCharset();
     $strWrapper = StringUtils::getWrapper($outputCharset);
     $lines = explode("\n", $strWrapper->wordWrap($this->content, $columnWidth, "\n", true));
     $paddedLines = array();
     foreach ($lines as $line) {
         $paddedLines[] = str_repeat(' ', $padding) . $strWrapper->strPad($line, $columnWidth, ' ', $padMode) . str_repeat(' ', $padding);
     }
     $result = implode("\n", $paddedLines);
     return $result;
 }
 /**
  * Render a text table containing the data provided, that will fit inside console window's width.
  *
  * @param  $data
  * @param  $cols
  * @param  $consoleWidth
  * @return string
  */
 protected function renderTable($data, $cols, $consoleWidth)
 {
     $result = '';
     $padding = 2;
     // If there is only 1 column, just concatenate it
     if ($cols == 1) {
         foreach ($data as $row) {
             $result .= $row[0] . "\n";
         }
         return $result;
     }
     // Get the string wrapper supporting UTF-8 character encoding
     $strWrapper = StringUtils::getWrapper('UTF-8');
     // Determine max width for each column
     $maxW = array();
     for ($x = 1; $x <= $cols; $x += 1) {
         $maxW[$x] = 0;
         foreach ($data as $row) {
             $maxW[$x] = max($maxW[$x], $strWrapper->strlen($row[$x - 1]) + $padding * 2);
         }
     }
     /*
      * Check if the sum of x-1 columns fit inside console window width - 10
      * chars. If columns do not fit inside console window, then we'll just
      * concatenate them and output as is.
      */
     $width = 0;
     for ($x = 1; $x < $cols; $x += 1) {
         $width += $maxW[$x];
     }
     if ($width >= $consoleWidth - 10) {
         foreach ($data as $row) {
             $result .= implode("    ", $row) . "\n";
         }
         return $result;
     }
     /*
      * Use Zend\Text\Table to render the table.
      * The last column will use the remaining space in console window
      * (minus 1 character to prevent double wrapping at the edge of the
      * screen).
      */
     $maxW[$cols] = $consoleWidth - $width - 1;
     $table = new Table\Table();
     $table->setColumnWidths($maxW);
     $table->setDecorator(new Table\Decorator\Blank());
     $table->setPadding(2);
     foreach ($data as $row) {
         $table->appendRow($row);
     }
     return $table->render();
 }
예제 #24
0
 /**
  * String padding
  *
  * @param  string  $input
  * @param  int $padLength
  * @param  string  $padString
  * @param  int $padType
  * @param  string  $charset
  * @return string
  * @deprecated Please use Zend\Stdlib\StringUtils instead
  */
 public static function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT, $charset = 'utf-8')
 {
     trigger_error(sprintf("This method is deprecated, please use '%s' instead", 'Zend\\Stdlib\\StringUtils::getWrapper(<charset>)->strPad'), E_USER_DEPRECATED);
     return StringUtils::getWrapper($charset)->strPad($input, $padLength, $padString, $padType);
 }
예제 #25
0
 /**
  * Set feed encoding
  *
  * @param  string $enc
  * @return Entry
  */
 public function setEncoding($enc)
 {
     $this->stringWrapper = StringUtils::getWrapper($enc);
     $this->encoding = $enc;
     return $this;
 }
예제 #26
0
 /**
  * @return bool
  * @deprecated Since 2.1.0
  */
 public static function hasPcreUnicodeSupport()
 {
     return StringUtils::hasPcreUnicodeSupport();
 }
예제 #27
0
 /**
  * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
  *
  * @param  float   $current       Current progress value
  * @param  float   $max           Max progress value
  * @param  float   $percent       Current percent value
  * @param  integer $timeTaken     Taken time in seconds
  * @param  integer $timeRemaining Remaining time in seconds
  * @param  string  $text          Status text
  * @return void
  */
 public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
 {
     // See if we must clear the line
     if ($this->outputStarted) {
         $data = str_repeat("", $this->width);
     } else {
         $data = '';
         $this->outputStarted = true;
     }
     // Build all elements
     $renderedElements = array();
     foreach ($this->elements as $element) {
         switch ($element) {
             case self::ELEMENT_BAR:
                 $visualWidth = $this->barWidth - 2;
                 $bar = '[';
                 $indicatorWidth = strlen($this->barIndicatorChar);
                 $doneWidth = min($visualWidth - $indicatorWidth, round($visualWidth * $percent));
                 if ($doneWidth > 0) {
                     $bar .= substr(str_repeat($this->barLeftChar, ceil($doneWidth / strlen($this->barLeftChar))), 0, $doneWidth);
                 }
                 $bar .= $this->barIndicatorChar;
                 $leftWidth = $visualWidth - $doneWidth - $indicatorWidth;
                 if ($leftWidth > 0) {
                     $bar .= substr(str_repeat($this->barRightChar, ceil($leftWidth / strlen($this->barRightChar))), 0, $leftWidth);
                 }
                 $bar .= ']';
                 $renderedElements[] = $bar;
                 break;
             case self::ELEMENT_PERCENT:
                 $renderedElements[] = str_pad(round($percent * 100), 3, ' ', STR_PAD_LEFT) . '%';
                 break;
             case self::ELEMENT_ETA:
                 // In the first 5 seconds we don't get accurate results,
                 // this skipping technique is found in many progressbar
                 // implementations.
                 if ($timeTaken < 5) {
                     $renderedElements[] = str_repeat(' ', 12);
                     break;
                 }
                 if ($timeRemaining === null || $timeRemaining > 86400) {
                     $etaFormatted = '??:??:??';
                 } else {
                     $hours = floor($timeRemaining / 3600);
                     $minutes = floor($timeRemaining % 3600 / 60);
                     $seconds = $timeRemaining % 3600 % 60;
                     $etaFormatted = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
                 }
                 $renderedElements[] = 'ETA ' . $etaFormatted;
                 break;
             case self::ELEMENT_TEXT:
                 $renderedElements[] = StringUtils::getWrapper($this->charset)->strPad(substr($text, 0, $this->textWidth), $this->textWidth, ' ', STR_PAD_RIGHT);
                 break;
         }
     }
     $data .= implode(' ', $renderedElements);
     // Output line data
     $this->_outputData($data);
 }
예제 #28
0
 /**
  * Render a FIGlet text
  *
  * @param  string $text     Text to convert to a figlet text
  * @param  string $encoding Encoding of the input string
  * @throws Exception\InvalidArgumentException When $text is not a string
  * @throws Exception\UnexpectedValueException When $text it not properly encoded
  * @return string
  */
 public function render($text, $encoding = 'UTF-8')
 {
     if (!is_string($text)) {
         throw new Exception\InvalidArgumentException('$text must be a string');
     }
     // Get the string wrapper supporting UTF-8 character encoding and the input encoding
     $strWrapper = StringUtils::getWrapper($encoding, 'UTF-8');
     // Convert $text to UTF-8 and check encoding
     $text = $strWrapper->convert($text);
     if (!StringUtils::isValidUtf8($text)) {
         throw new Exception\UnexpectedValueException('$text is not encoded with ' . $encoding);
     }
     $strWrapper = StringUtils::getWrapper('UTF-8');
     $this->output = '';
     $this->outputLine = array();
     $this->_clearLine();
     $this->outlineLengthLimit = $this->outputWidth - 1;
     $this->inCharLineLengthLimit = $this->outputWidth * 4 + 100;
     $wordBreakMode = 0;
     $lastCharWasEol = false;
     $textLength = $strWrapper->strlen($text);
     for ($charNum = 0; $charNum < $textLength; $charNum++) {
         // Handle paragraphs
         $char = $strWrapper->substr($text, $charNum, 1);
         if ($char === "\n" && $this->handleParagraphs && !$lastCharWasEol) {
             $nextChar = $strWrapper->substr($text, $charNum + 1, 1);
             if (!$nextChar) {
                 $nextChar = null;
             }
             $char = ctype_space($nextChar) ? "\n" : ' ';
         }
         $lastCharWasEol = ctype_space($char) && $char !== "\t" && $char !== ' ';
         if (ctype_space($char)) {
             $char = $char === "\t" || $char === ' ' ? ' ' : "\n";
         }
         // Skip unprintable characters
         $ordChar = $this->_uniOrd($char);
         if ($ordChar > 0 && $ordChar < 32 && $char !== "\n" || $ordChar === 127) {
             continue;
         }
         // Build the character
         // Note: The following code is complex and thoroughly tested.
         // Be careful when modifying!
         do {
             $charNotAdded = false;
             if ($wordBreakMode === -1) {
                 if ($char === ' ') {
                     break;
                 } elseif ($char === "\n") {
                     $wordBreakMode = 0;
                     break;
                 }
                 $wordBreakMode = 0;
             }
             if ($char === "\n") {
                 $this->_appendLine();
                 $wordBreakMode = false;
             } elseif ($this->_addChar($char)) {
                 if ($char !== ' ') {
                     $wordBreakMode = $wordBreakMode >= 2 ? 3 : 1;
                 } else {
                     $wordBreakMode = $wordBreakMode > 0 ? 2 : 0;
                 }
             } elseif ($this->outlineLength === 0) {
                 for ($i = 0; $i < $this->charHeight; $i++) {
                     if ($this->rightToLeft === 1 && $this->outputWidth > 1) {
                         $offset = strlen($this->currentChar[$i]) - $this->outlineLengthLimit;
                         $this->_putString(substr($this->currentChar[$i], $offset));
                     } else {
                         $this->_putString($this->currentChar[$i]);
                     }
                 }
                 $wordBreakMode = -1;
             } elseif ($char === ' ') {
                 if ($wordBreakMode === 2) {
                     $this->_splitLine();
                 } else {
                     $this->_appendLine();
                 }
                 $wordBreakMode = -1;
             } else {
                 if ($wordBreakMode >= 2) {
                     $this->_splitLine();
                 } else {
                     $this->_appendLine();
                 }
                 $wordBreakMode = $wordBreakMode === 3 ? 1 : 0;
                 $charNotAdded = true;
             }
         } while ($charNotAdded);
     }
     if ($this->outlineLength !== 0) {
         $this->_appendLine();
     }
     return $this->output;
 }
예제 #29
0
 /**
  * Get a list of supported character encodings
  *
  * @return string[]
  */
 public static function getSupportedEncodings()
 {
     return StringUtils::getSingleByteEncodings();
 }
예제 #30
0
    public function testHasPcreUnicodeSupport()
    {
        ErrorHandler::start();
        $expected = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1;
        ErrorHandler::stop();

        $this->assertSame($expected, StringUtils::hasPcreUnicodeSupport());
    }