pax_global_header00006660000000000000000000000064135371262630014522gustar00rootroot0000000000000052 comment=68609e1261d215ea5b21b7987539cbfbe156ec3e exporter-3.1.2/000077500000000000000000000000001353712626300133755ustar00rootroot00000000000000exporter-3.1.2/.github/000077500000000000000000000000001353712626300147355ustar00rootroot00000000000000exporter-3.1.2/.github/FUNDING.yml000066400000000000000000000000241353712626300165460ustar00rootroot00000000000000patreon: s_bergmann exporter-3.1.2/.gitignore000066400000000000000000000000661353712626300153670ustar00rootroot00000000000000/.idea /composer.lock /vendor /.php_cs /.php_cs.cache exporter-3.1.2/.php_cs.dist000066400000000000000000000171141353712626300156200ustar00rootroot00000000000000 For the full copyright and license information, please view the LICENSE file that was distributed with this source code. EOF; return PhpCsFixer\Config::create() ->setRiskyAllowed(true) ->setRules( [ 'align_multiline_comment' => true, 'array_indentation' => true, 'array_syntax' => ['syntax' => 'short'], 'binary_operator_spaces' => [ 'operators' => [ '=' => 'align', '=>' => 'align', ], ], 'blank_line_after_namespace' => true, 'blank_line_before_statement' => [ 'statements' => [ 'break', 'continue', 'declare', 'do', 'for', 'foreach', 'if', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', ], ], 'braces' => true, 'cast_spaces' => true, 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], 'combine_consecutive_issets' => true, 'combine_consecutive_unsets' => true, 'compact_nullable_typehint' => true, 'concat_space' => ['spacing' => 'one'], 'declare_equal_normalize' => ['space' => 'none'], 'declare_strict_types' => true, 'dir_constant' => true, 'elseif' => true, 'encoding' => true, 'full_opening_tag' => true, 'function_declaration' => true, 'header_comment' => ['header' => $header, 'separate' => 'none'], 'indentation_type' => true, 'is_null' => true, 'line_ending' => true, 'list_syntax' => ['syntax' => 'short'], 'logical_operators' => true, 'lowercase_cast' => true, 'lowercase_constants' => true, 'lowercase_keywords' => true, 'lowercase_static_reference' => true, 'magic_constant_casing' => true, 'method_argument_space' => ['ensure_fully_multiline' => true], 'modernize_types_casting' => true, 'multiline_comment_opening_closing' => true, 'multiline_whitespace_before_semicolons' => true, 'native_constant_invocation' => true, 'native_function_casing' => true, 'native_function_invocation' => true, 'new_with_braces' => false, 'no_alias_functions' => true, 'no_alternative_syntax' => true, 'no_blank_lines_after_class_opening' => true, 'no_blank_lines_after_phpdoc' => true, 'no_blank_lines_before_namespace' => true, 'no_closing_tag' => true, 'no_empty_comment' => true, 'no_empty_phpdoc' => true, 'no_empty_statement' => true, 'no_extra_blank_lines' => true, 'no_homoglyph_names' => true, 'no_leading_import_slash' => true, 'no_leading_namespace_whitespace' => true, 'no_mixed_echo_print' => ['use' => 'print'], 'no_multiline_whitespace_around_double_arrow' => true, 'no_null_property_initialization' => true, 'no_php4_constructor' => true, 'no_short_bool_cast' => true, 'no_short_echo_tag' => true, 'no_singleline_whitespace_before_semicolons' => true, 'no_spaces_after_function_name' => true, 'no_spaces_inside_parenthesis' => true, 'no_superfluous_elseif' => true, 'no_superfluous_phpdoc_tags' => true, 'no_trailing_comma_in_list_call' => true, 'no_trailing_comma_in_singleline_array' => true, 'no_trailing_whitespace' => true, 'no_trailing_whitespace_in_comment' => true, 'no_unneeded_control_parentheses' => true, 'no_unneeded_curly_braces' => true, 'no_unneeded_final_method' => true, 'no_unreachable_default_argument_value' => true, 'no_unset_on_property' => true, 'no_unused_imports' => true, 'no_useless_else' => true, 'no_useless_return' => true, 'no_whitespace_before_comma_in_array' => true, 'no_whitespace_in_blank_line' => true, 'non_printable_character' => true, 'normalize_index_brace' => true, 'object_operator_without_whitespace' => true, 'ordered_class_elements' => [ 'order' => [ 'use_trait', 'constant_public', 'constant_protected', 'constant_private', 'property_public_static', 'property_protected_static', 'property_private_static', 'property_public', 'property_protected', 'property_private', 'method_public_static', 'construct', 'destruct', 'magic', 'phpunit', 'method_public', 'method_protected', 'method_private', 'method_protected_static', 'method_private_static', ], ], 'ordered_imports' => true, 'phpdoc_add_missing_param_annotation' => true, 'phpdoc_align' => true, 'phpdoc_annotation_without_dot' => true, 'phpdoc_indent' => true, 'phpdoc_no_access' => true, 'phpdoc_no_empty_return' => true, 'phpdoc_no_package' => true, 'phpdoc_order' => true, 'phpdoc_return_self_reference' => true, 'phpdoc_scalar' => true, 'phpdoc_separation' => true, 'phpdoc_single_line_var_spacing' => true, 'phpdoc_to_comment' => true, 'phpdoc_trim' => true, 'phpdoc_trim_consecutive_blank_line_separation' => true, 'phpdoc_types' => true, 'phpdoc_types_order' => true, 'phpdoc_var_without_name' => true, 'pow_to_exponentiation' => true, 'protected_to_private' => true, 'return_assignment' => true, 'return_type_declaration' => ['space_before' => 'none'], 'self_accessor' => true, 'semicolon_after_instruction' => true, 'set_type_to_cast' => true, 'short_scalar_cast' => true, 'simplified_null_return' => true, 'single_blank_line_at_eof' => true, 'single_import_per_statement' => true, 'single_line_after_imports' => true, 'single_quote' => true, 'standardize_not_equals' => true, 'ternary_to_null_coalescing' => true, 'trim_array_spaces' => true, 'unary_operator_spaces' => true, 'visibility_required' => true, //'void_return' => true, 'whitespace_after_comma_in_array' => true, ] ) ->setFinder( PhpCsFixer\Finder::create() ->files() ->in(__DIR__ . '/src') ->in(__DIR__ . '/tests') ); exporter-3.1.2/.travis.yml000066400000000000000000000006521353712626300155110ustar00rootroot00000000000000language: php php: - 7.0 - 7.1 - 7.2 - 7.3 - 7.4snapshot before_install: - composer self-update - composer clear-cache install: - travis_retry composer update --no-interaction --no-ansi --no-progress --no-suggest --optimize-autoloader --prefer-stable script: - ./vendor/bin/phpunit --coverage-clover=coverage.xml after_success: - bash <(curl -s https://codecov.io/bash) notifications: email: false exporter-3.1.2/ChangeLog.md000066400000000000000000000006661353712626300155560ustar00rootroot00000000000000# ChangeLog All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. ## [3.1.2] - 2019-09-14 ### Fixed * Fixed [#29](https://github.com/sebastianbergmann/exporter/pull/29): Second parameter for `str_repeat()` must be an integer ### Removed * Remove HHVM-specific code that is no longer needed [3.1.2]: https://github.com/sebastianbergmann/exporter/compare/3.1.1...3.1.2 exporter-3.1.2/LICENSE000066400000000000000000000030071353712626300144020ustar00rootroot00000000000000Exporter Copyright (c) 2002-2019, Sebastian Bergmann . 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. exporter-3.1.2/README.md000066400000000000000000000054711353712626300146630ustar00rootroot00000000000000Exporter ======== [![Build Status](https://secure.travis-ci.org/sebastianbergmann/exporter.png?branch=master)](https://travis-ci.org/sebastianbergmann/exporter) This component provides the functionality to export PHP variables for visualization. ## Usage Exporting: ```php '' 'string' => '' 'code' => 0 'file' => '/home/sebastianbergmann/test.php' 'line' => 34 'previous' => null ) */ print $exporter->export(new Exception); ``` ## Data Types Exporting simple types: ```php export(46); // 4.0 print $exporter->export(4.0); // 'hello, world!' print $exporter->export('hello, world!'); // false print $exporter->export(false); // NAN print $exporter->export(acos(8)); // -INF print $exporter->export(log(0)); // null print $exporter->export(null); // resource(13) of type (stream) print $exporter->export(fopen('php://stderr', 'w')); // Binary String: 0x000102030405 print $exporter->export(chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5)); ``` Exporting complex types: ```php Array &1 ( 0 => 1 1 => 2 2 => 3 ) 1 => Array &2 ( 0 => '' 1 => 0 2 => false ) ) */ print $exporter->export(array(array(1,2,3), array("",0,FALSE))); /* Array &0 ( 'self' => Array &1 ( 'self' => Array &1 ) ) */ $array = array(); $array['self'] = &$array; print $exporter->export($array); /* stdClass Object &0000000003a66dcc0000000025e723e2 ( 'self' => stdClass Object &0000000003a66dcc0000000025e723e2 ) */ $obj = new stdClass(); $obj->self = $obj; print $exporter->export($obj); ``` Compact exports: ```php shortenedExport(array()); // Array (...) print $exporter->shortenedExport(array(1,2,3,4,5)); // stdClass Object () print $exporter->shortenedExport(new stdClass); // Exception Object (...) print $exporter->shortenedExport(new Exception); // this\nis\na\nsuper\nlong\nstring\nt...\nspace print $exporter->shortenedExport( << exporter-3.1.2/composer.json000066400000000000000000000023661353712626300161260ustar00rootroot00000000000000{ "name": "sebastian/exporter", "description": "Provides the functionality to export PHP variables for visualization", "keywords": ["exporter","export"], "homepage": "http://www.github.com/sebastianbergmann/exporter", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" }, { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" } ], "config": { "optimize-autoloader": true, "sort-packages": true }, "prefer-stable": true, "require": { "php": "^7.0", "sebastian/recursion-context": "^3.0" }, "require-dev": { "phpunit/phpunit": "^6.0", "ext-mbstring": "*" }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-master": "3.1.x-dev" } } } exporter-3.1.2/phpunit.xml000066400000000000000000000012651353712626300156120ustar00rootroot00000000000000 tests src exporter-3.1.2/src/000077500000000000000000000000001353712626300141645ustar00rootroot00000000000000exporter-3.1.2/src/Exporter.php000066400000000000000000000215151353712626300165110ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Exporter; use SebastianBergmann\RecursionContext\Context; /** * A nifty utility for visualizing PHP variables. * * * export(new Exception); * */ class Exporter { /** * Exports a value as 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 int $indentation The indentation level of the 2nd+ line * * @return string */ public function export($value, $indentation = 0) { return $this->recursiveExport($value, $indentation); } /** * @param array $data * @param Context $context * * @return string */ public function shortenedRecursiveExport(&$data, Context $context = null) { $result = []; $exporter = new self(); if (!$context) { $context = new Context; } $array = $data; $context->add($data); foreach ($array as $key => $value) { if (\is_array($value)) { if ($context->contains($data[$key]) !== false) { $result[] = '*RECURSION*'; } else { $result[] = \sprintf( 'array(%s)', $this->shortenedRecursiveExport($data[$key], $context) ); } } else { $result[] = $exporter->shortenedExport($value); } } return \implode(', ', $result); } /** * Exports a value into a single-line string * * The output of this method is similar to the output of * SebastianBergmann\Exporter\Exporter::export(). * * Newlines are replaced by the visible string '\n'. * Contents of arrays and objects (if any) are replaced by '...'. * * @return string * * @see SebastianBergmann\Exporter\Exporter::export */ public function shortenedExport($value) { if (\is_string($value)) { $string = \str_replace("\n", '', $this->export($value)); if (\function_exists('mb_strlen')) { if (\mb_strlen($string) > 40) { $string = \mb_substr($string, 0, 30) . '...' . \mb_substr($string, -7); } } else { if (\strlen($string) > 40) { $string = \substr($string, 0, 30) . '...' . \substr($string, -7); } } return $string; } if (\is_object($value)) { return \sprintf( '%s Object (%s)', \get_class($value), \count($this->toArray($value)) > 0 ? '...' : '' ); } if (\is_array($value)) { return \sprintf( 'Array (%s)', \count($value) > 0 ? '...' : '' ); } return $this->export($value); } /** * Converts an object to an array containing all of its private, protected * and public properties. * * @return array */ public function toArray($value) { if (!\is_object($value)) { return (array) $value; } $array = []; foreach ((array) $value as $key => $val) { // Exception traces commonly reference hundreds to thousands of // objects currently loaded in memory. Including them in the result // has a severe negative performance impact. if ("\0Error\0trace" === $key || "\0Exception\0trace" === $key) { continue; } // 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(.+)$/', (string) $key, $matches)) { $key = $matches[1]; } // See https://github.com/php/php-src/commit/5721132 if ($key === "\0gcdata") { continue; } $array[$key] = $val; } // Some internal classes like SplObjectStorage don't work with the // above (fast) mechanism nor with reflection in Zend. // Format the output similarly to print_r() in this case if ($value instanceof \SplObjectStorage) { foreach ($value as $key => $val) { $array[\spl_object_hash($val)] = [ 'obj' => $val, 'inf' => $value->getInfo(), ]; } } return $array; } /** * Recursive implementation of export * * @param mixed $value The value to export * @param int $indentation The indentation level of the 2nd+ line * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects * * @return string * * @see SebastianBergmann\Exporter\Exporter::export */ protected function recursiveExport(&$value, $indentation, $processed = null) { if ($value === null) { return 'null'; } if ($value === true) { return 'true'; } if ($value === false) { return 'false'; } if (\is_float($value) && (float) ((int) $value) === $value) { return "$value.0"; } if (\is_resource($value)) { return \sprintf( 'resource(%d) of type (%s)', $value, \get_resource_type($value) ); } if (\is_string($value)) { // Match for most non printable chars somewhat taking multibyte chars into account if (\preg_match('/[^\x09-\x0d\x1b\x20-\xff]/', $value)) { return 'Binary String: 0x' . \bin2hex($value); } return "'" . \str_replace( '', "\n", \str_replace( ["\r\n", "\n\r", "\r", "\n"], ['\r\n', '\n\r', '\r', '\n'], $value ) ) . "'"; } $whitespace = \str_repeat(' ', (int)(4 * $indentation)); if (!$processed) { $processed = new Context; } if (\is_array($value)) { if (($key = $processed->contains($value)) !== false) { return 'Array &' . $key; } $array = $value; $key = $processed->add($value); $values = ''; if (\count($array) > 0) { foreach ($array as $k => $v) { $values .= \sprintf( '%s %s => %s' . "\n", $whitespace, $this->recursiveExport($k, $indentation), $this->recursiveExport($value[$k], $indentation + 1, $processed) ); } $values = "\n" . $values . $whitespace; } return \sprintf('Array &%s (%s)', $key, $values); } if (\is_object($value)) { $class = \get_class($value); if ($hash = $processed->contains($value)) { return \sprintf('%s Object &%s', $class, $hash); } $hash = $processed->add($value); $values = ''; $array = $this->toArray($value); if (\count($array) > 0) { foreach ($array as $k => $v) { $values .= \sprintf( '%s %s => %s' . "\n", $whitespace, $this->recursiveExport($k, $indentation), $this->recursiveExport($v, $indentation + 1, $processed) ); } $values = "\n" . $values . $whitespace; } return \sprintf('%s Object &%s (%s)', $class, $hash, $values); } return \var_export($value, true); } } exporter-3.1.2/tests/000077500000000000000000000000001353712626300145375ustar00rootroot00000000000000exporter-3.1.2/tests/ExporterTest.php000066400000000000000000000270021353712626300177210ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Exporter; use PHPUnit\Framework\TestCase; use SebastianBergmann\RecursionContext\Context; /** * @covers SebastianBergmann\Exporter\Exporter */ class ExporterTest extends TestCase { /** * @var Exporter */ private $exporter; protected function setUp() { $this->exporter = new Exporter; } public function exportProvider() { $obj2 = new \stdClass; $obj2->foo = 'bar'; $obj3 = (object) [1, 2, "Test\r\n", 4, 5, 6, 7, 8]; $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 = ['foo' => 'bar']; $obj->self = $obj; $storage = new \SplObjectStorage; $storage->attach($obj2); $storage->foo = $obj2; return [ 'export null' => [null, 'null'], 'export boolean true' => [true, 'true'], 'export boolean false' => [false, 'false'], 'export int 1' => [1, '1'], 'export float 1.0' => [1.0, '1.0'], 'export float 1.2' => [1.2, '1.2'], 'export stream' => [\fopen('php://memory', 'r'), 'resource(%d) of type (stream)'], 'export numeric string' => ['1', "'1'"], 'export multidimentional array' => [[[1, 2, 3], [3, 4, 5]], << Array &1 ( 0 => 1 1 => 2 2 => 3 ) 1 => Array &2 ( 0 => 3 1 => 4 2 => 5 ) ) EOF ], // \n\r and \r is converted to \n 'export multiline text' => ["this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", << [new \stdClass, 'stdClass Object &%x ()'], 'export non empty stdclass' => [$obj, << null 'boolean' => true 'integer' => 1 'double' => 1.2 'string' => '1' 'text' => 'this\\n is\\n a\\n very\\n very\\n very\\n very\\n very\\n very\\r long\\n\\r text' 'object' => stdClass Object &%x ( 'foo' => 'bar' ) 'objectagain' => stdClass Object &%x 'array' => Array &%d ( 'foo' => 'bar' ) 'self' => stdClass Object &%x ) EOF ], 'export empty array' => [[], 'Array &%d ()'], 'export splObjectStorage' => [$storage, << stdClass Object &%x ( 'foo' => 'bar' ) '%x' => Array &0 ( 'obj' => stdClass Object &%x 'inf' => null ) ) EOF ], 'export stdClass with numeric properties' => [$obj3, << 1 1 => 2 2 => 'Test\\r\\n ' 3 => 4 4 => 5 5 => 6 6 => 7 7 => 8 ) EOF ], [ \chr(0) . \chr(1) . \chr(2) . \chr(3) . \chr(4) . \chr(5), 'Binary String: 0x000102030405' ], [ \implode('', \array_map('chr', \range(0x0e, 0x1f))), 'Binary String: 0x0e0f101112131415161718191a1b1c1d1e1f' ], [ \chr(0x00) . \chr(0x09), 'Binary String: 0x0009' ], [ '', "''" ], 'export Exception without trace' => [ new \Exception('The exception message', 42), << 'The exception message' 'string' => '' 'code' => 42 'file' => '%s/tests/ExporterTest.php' 'line' => %d 'previous' => null ) EOF ], 'export Error without trace' => [ new \Error('The exception message', 42), << 'The exception message' 'string' => '' 'code' => 42 'file' => '%s/tests/ExporterTest.php' 'line' => %d 'previous' => null ) EOF ], ]; } /** * @dataProvider exportProvider */ public function testExport($value, $expected) { $this->assertStringMatchesFormat( $expected, $this->trimNewline($this->exporter->export($value)) ); } public function testExport2() { if (\PHP_VERSION === '5.3.3') { $this->markTestSkipped('Skipped due to "Nesting level too deep - recursive dependency?" fatal error'); } $obj = new \stdClass; $obj->foo = 'bar'; $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' => $obj, 'objectagain' => $obj, 'array' => ['foo' => 'bar'], ]; $array['self'] = &$array; $expected = << 0 'null' => null 'boolean' => true 'integer' => 1 'double' => 1.2 'string' => '1' 'text' => 'this\\n is\\n a\\n very\\n very\\n very\\n very\\n very\\n very\\r long\\n\\r text' 'object' => stdClass Object &%x ( 'foo' => 'bar' ) 'objectagain' => stdClass Object &%x 'array' => Array &%d ( 'foo' => 'bar' ) 'self' => Array &%d ( 0 => 0 'null' => null 'boolean' => true 'integer' => 1 'double' => 1.2 'string' => '1' 'text' => 'this\\n is\\n a\\n very\\n very\\n very\\n very\\n very\\n very\\r long\\n\\r text' 'object' => stdClass Object &%x 'objectagain' => stdClass Object &%x 'array' => Array &%d ( 'foo' => 'bar' ) 'self' => Array &%d ) ) EOF; $this->assertStringMatchesFormat( $expected, $this->trimNewline($this->exporter->export($array)) ); } public function shortenedExportProvider() { $obj = new \stdClass; $obj->foo = 'bar'; $array = [ 'foo' => 'bar', ]; return [ 'shortened export null' => [null, 'null'], 'shortened export boolean true' => [true, 'true'], 'shortened export integer 1' => [1, '1'], 'shortened export float 1.0' => [1.0, '1.0'], 'shortened export float 1.2' => [1.2, '1.2'], 'shortened export numeric string' => ['1', "'1'"], // \n\r and \r is converted to \n 'shortened export multilinestring' => ["this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", "'this\\nis\\na\\nvery\\nvery\\nvery...\\rtext'"], 'shortened export empty stdClass' => [new \stdClass, 'stdClass Object ()'], 'shortened export not empty stdClass' => [$obj, 'stdClass Object (...)'], 'shortened export empty array' => [[], 'Array ()'], 'shortened export not empty array' => [$array, 'Array (...)'], ]; } /** * @dataProvider shortenedExportProvider */ public function testShortenedExport($value, $expected) { $this->assertSame( $expected, $this->trimNewline($this->exporter->shortenedExport($value)) ); } /** * @requires extension mbstring */ public function testShortenedExportForMultibyteCharacters() { $oldMbLanguage = \mb_language(); \mb_language('Japanese'); $oldMbInternalEncoding = \mb_internal_encoding(); \mb_internal_encoding('UTF-8'); try { $this->assertSame( "'いろはにほへとちりぬるをわかよたれそつねならむうゐのおくや...しゑひもせす'", $this->trimNewline($this->exporter->shortenedExport('いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす')) ); } catch (\Exception $e) { \mb_internal_encoding($oldMbInternalEncoding); \mb_language($oldMbLanguage); throw $e; } \mb_internal_encoding($oldMbInternalEncoding); \mb_language($oldMbLanguage); } public function provideNonBinaryMultibyteStrings() { return [ [\implode('', \array_map('chr', \range(0x09, 0x0d))), 9], [\implode('', \array_map('chr', \range(0x20, 0x7f))), 96], [\implode('', \array_map('chr', \range(0x80, 0xff))), 128], ]; } /** * @dataProvider provideNonBinaryMultibyteStrings */ public function testNonBinaryStringExport($value, $expectedLength) { $this->assertRegExp( "~'.{{$expectedLength}}'\$~s", $this->exporter->export($value) ); } public function testNonObjectCanBeReturnedAsArray() { $this->assertEquals([true], $this->exporter->toArray(true)); } public function testIgnoreKeysInValue() { // Find out what the actual use case was with the PHP bug $array = []; $array["\0gcdata"] = ''; $this->assertEquals([], $this->exporter->toArray((object) $array)); } private function trimNewline($string) { return \preg_replace('/[ ]*\n/', "\n", $string); } /** * @dataProvider shortenedRecursiveExportProvider */ public function testShortenedRecursiveExport(array $value, string $expected) { $this->assertEquals($expected, $this->exporter->shortenedRecursiveExport($value)); } public function shortenedRecursiveExportProvider() { return [ 'export null' => [[null], 'null'], 'export boolean true' => [[true], 'true'], 'export boolean false' => [[false], 'false'], 'export int 1' => [[1], '1'], 'export float 1.0' => [[1.0], '1.0'], 'export float 1.2' => [[1.2], '1.2'], 'export numeric string' => [['1'], "'1'"], 'export with numeric array key' => [[2 => 1], '1'], 'export with assoc array key' => [['foo' => 'bar'], '\'bar\''], 'export multidimentional array' => [[[1, 2, 3], [3, 4, 5]], 'array(1, 2, 3), array(3, 4, 5)'], 'export object' => [[new \stdClass], 'stdClass Object ()'], ]; } public function testShortenedRecursiveOccurredRecursion() { $recursiveValue = [1]; $context = new Context(); $context->add($recursiveValue); $value = [$recursiveValue]; $this->assertEquals('*RECURSION*', $this->exporter->shortenedRecursiveExport($value, $context)); } }