pax_global_header00006660000000000000000000000064125414670110014513gustar00rootroot0000000000000052 comment=7ae5513327cb536431847bcc0c10edba2701064e exporter-1.2.1/000077500000000000000000000000001254146701100133645ustar00rootroot00000000000000exporter-1.2.1/.gitignore000066400000000000000000000001611254146701100153520ustar00rootroot00000000000000.idea phpunit.xml composer.lock composer.phar vendor/ cache.properties build/LICENSE build/README.md build/*.tgz exporter-1.2.1/.travis.yml000066400000000000000000000005361254146701100155010ustar00rootroot00000000000000language: php before_script: - composer self-update - composer install --no-interaction --prefer-source --dev php: - 5.3.3 - 5.3 - 5.4 - 5.5 - 5.6 - hhvm notifications: email: false webhooks: urls: - https://webhooks.gitter.im/e/6668f52f3dd4e3f81960 on_success: always on_failure: always on_start: false exporter-1.2.1/LICENSE000066400000000000000000000030071254146701100143710ustar00rootroot00000000000000Exporter Copyright (c) 2002-2015, 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-1.2.1/README.md000066400000000000000000000054761254146701100146570ustar00rootroot00000000000000Exporter ======== [![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 'trace' => Array &0 () '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-1.2.1/composer.json000066400000000000000000000021551254146701100161110ustar00rootroot00000000000000{ "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@2bepublished.at" } ], "require": { "php": ">=5.3.3", "sebastian/recursion-context": "~1.0" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } } } exporter-1.2.1/phpunit.xml.dist000066400000000000000000000012161254146701100165370ustar00rootroot00000000000000 tests src exporter-1.2.1/src/000077500000000000000000000000001254146701100141535ustar00rootroot00000000000000exporter-1.2.1/src/Exporter.php000066400000000000000000000211331254146701100164740ustar00rootroot00000000000000 * * 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 mixed $value * @param int $indentation The indentation level of the 2nd+ line * @return string */ public function export($value, $indentation = 0) { return $this->recursiveExport($value, $indentation); } /** * @param mixed $data * @param Context $context * @return string */ public function shortenedRecursiveExport(&$data, Context $context = null) { $result = array(); $exporter = new self(); if (!$context) { $context = new Context; } $context->add($data); foreach ($data 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. This method guarantees * thought that the result contains now newlines. * * Newlines are replaced by the visible string '\n'. Contents of arrays * and objects (if any) are replaced by '...'. * * @param mixed $value * @return string * @see SebastianBergmann\Exporter\Exporter::export */ public function shortenedExport($value) { if (is_string($value)) { $string = $this->export($value); if (strlen($string) > 40) { $string = substr($string, 0, 30) . '...' . substr($string, -7); } return str_replace("\n", '\n', $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. * * @param mixed $value * @return array */ public function toArray($value) { if (!is_object($value)) { return (array) $value; } $array = array(); foreach ((array) $value as $key => $val) { // properties are transformed to keys in the following way: // private $property => "\0Classname\0property" // protected $property => "\0*\0property" // public $property => "property" if (preg_match('/^\0.+\0(.+)$/', $key, $matches)) { $key = $matches[1]; } // 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) { // However, the fast method does work in HHVM, and exposes the // internal implementation. Hide it again. if (property_exists('\SplObjectStorage', '__storage')) { unset($array['__storage']); } elseif (property_exists('\SplObjectStorage', 'storage')) { unset($array['storage']); } if (property_exists('\SplObjectStorage', '__key')) { unset($array['__key']); } foreach ($value as $key => $val) { $array[spl_object_hash($val)] = array( '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) && floatval(intval($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\x20-\xff]/', $value)) { return 'Binary String: 0x' . bin2hex($value); } return "'" . str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) . "'"; } $whitespace = str_repeat(' ', 4 * $indentation); if (!$processed) { $processed = new Context; } if (is_array($value)) { if (($key = $processed->contains($value)) !== false) { return 'Array &' . $key; } $key = $processed->add($value); $values = ''; if (count($value) > 0) { foreach ($value 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-1.2.1/tests/000077500000000000000000000000001254146701100145265ustar00rootroot00000000000000exporter-1.2.1/tests/ExporterTest.php000066400000000000000000000163221254146701100177130ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Exporter; /** * @covers SebastianBergmann\Exporter\Exporter */ class ExporterTest extends \PHPUnit_Framework_TestCase { /** * @var Exporter */ private $exporter; protected function setUp() { $this->exporter = new Exporter; } public function exportProvider() { $obj2 = new \stdClass; $obj2->foo = 'bar'; $obj3 = (object)array(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 = array('foo' => 'bar'); $obj->self = $obj; $storage = new \SplObjectStorage; $storage->attach($obj2); $storage->foo = $obj2; return array( array(null, 'null'), array(true, 'true'), array(false, 'false'), array(1, '1'), array(1.0, '1.0'), array(1.2, '1.2'), array(fopen('php://memory', 'r'), 'resource(%d) of type (stream)'), array('1', "'1'"), array(array(array(1,2,3), array(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 array("this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", << null 'boolean' => true 'integer' => 1 'double' => 1.2 'string' => '1' 'text' => 'this is a very very very very very very long text' 'object' => stdClass Object &%x ( 'foo' => 'bar' ) 'objectagain' => stdClass Object &%x 'array' => Array &%d ( 'foo' => 'bar' ) 'self' => stdClass Object &%x ) EOF ), array(array(), 'Array &%d ()'), array($storage, << stdClass Object &%x ( 'foo' => 'bar' ) '%x' => Array &0 ( 'obj' => stdClass Object &%x 'inf' => null ) ) EOF ), array($obj3, << 1 1 => 2 2 => 'Test\n' 3 => 4 4 => 5 5 => 6 6 => 7 7 => 8 ) EOF ), array( chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5), 'Binary String: 0x000102030405' ), array( implode('', array_map('chr', range(0x0e, 0x1f))), 'Binary String: 0x0e0f101112131415161718191a1b1c1d1e1f' ), array( chr(0x00) . chr(0x09), 'Binary String: 0x0009' ), array( '', "''" ), ); } /** * @dataProvider exportProvider */ public function testExport($value, $expected) { $this->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 = 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' => array('foo' => 'bar'), ); $array['self'] = &$array; $expected = << 0 'null' => null 'boolean' => true 'integer' => 1 'double' => 1.2 'string' => '1' 'text' => 'this is a very very very very very very long text' 'object' => stdClass Object &%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 is a very very very very very very long 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 = array( 'foo' => 'bar', ); return array( array(null, 'null'), array(true, 'true'), array(1, '1'), array(1.0, '1.0'), array(1.2, '1.2'), array('1', "'1'"), // \n\r and \r is converted to \n array("this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", "'this\\nis\\na\\nvery\\nvery\\nvery\\nvery...g\\ntext'"), array(new \stdClass, 'stdClass Object ()'), array($obj, 'stdClass Object (...)'), array(array(), 'Array ()'), array($array, 'Array (...)'), ); } /** * @dataProvider shortenedExportProvider */ public function testShortenedExport($value, $expected) { $this->assertSame( $expected, $this->trimNewline($this->exporter->shortenedExport($value)) ); } public function provideNonBinaryMultibyteStrings() { return array( array(implode('', array_map('chr', range(0x09, 0x0d))), 5), array(implode('', array_map('chr', range(0x20, 0x7f))), 96), array(implode('', array_map('chr', range(0x80, 0xff))), 128), ); } /** * @dataProvider provideNonBinaryMultibyteStrings */ public function testNonBinaryStringExport($value, $expectedLength) { $this->assertRegExp( "~'.{{$expectedLength}}'\$~s", $this->exporter->export($value) ); } public function testNonObjectCanBeReturnedAsArray() { $this->assertEquals(array(true), $this->exporter->toArray(true)); } private function trimNewline($string) { return preg_replace('/[ ]*\n/', "\n", $string); } }