├── tests ├── data │ └── smallimage.png └── EmbedImagesTest.php ├── .travis.yml ├── src ├── AutoEmbedServiceProvider.php └── ImagesToAttachments.php ├── phpunit.xml ├── composer.json ├── LICENSE └── composer.lock /tests/data/smallimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molteber/puz-autoembed/HEAD/tests/data/smallimage.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.5 5 | - 5.6 6 | 7 | before_script: 8 | - travis_retry composer self-update 9 | - travis_retry composer install --prefer-source --no-interaction --dev 10 | 11 | script: phpunit 12 | -------------------------------------------------------------------------------- /src/AutoEmbedServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->make('mailer')->getSwiftMailer()->registerPlugin(new ImagesToAttachments); 12 | } 13 | 14 | /** 15 | * Register the service provider. 16 | * 17 | * @return void 18 | */ 19 | public function register() 20 | { 21 | // TODO: Nothing 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puz/mail_autoembed", 3 | "description": "Automatically embed all image sources in your emails", 4 | "license": "MIT", 5 | "keywords": ["laravel", "email", "mail", "image", "embed", "attach"], 6 | "require": { 7 | "swiftmailer/swiftmailer": "~5.1", 8 | "illuminate/support": "^5.2" 9 | }, 10 | "require-dev": { 11 | "phpunit/phpunit": "~4.8" 12 | }, 13 | "authors": [ 14 | { 15 | "name": "Morten Mehus", 16 | "email": "me@molty.no" 17 | } 18 | ], 19 | "autoload": { 20 | "psr-4": { 21 | "Puz\\Mail\\AutoEmbed\\": "src/" 22 | } 23 | }, 24 | "suggest": { 25 | "illuminate/support": "Required to connect to Laravel with the service provider" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Morten Mehus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/ImagesToAttachments.php: -------------------------------------------------------------------------------- 1 | message = $event->getMessage(); 39 | 40 | // Simply attach all the images you can find 41 | $this->attachImages(); 42 | } 43 | 44 | public function sendPerformed(Swift_Events_SendEvent $evt) 45 | { 46 | // Delete all the temp files after sending the message 47 | foreach ($this->tempFiles as $file) { 48 | unlink($file); 49 | } 50 | } 51 | 52 | protected function attachImages() 53 | { 54 | /* 55 | * Does anyone have a better solution to detect images in given string? 56 | * RegEx is NOT an optimal solution if given a inline data string. That's why I had to go for something like 57 | * this (explode everywhere!) to not break some of the images and emails 58 | */ 59 | $images = explode("message->getBody()); 60 | $imageCount = count($images); 61 | if ($imageCount > 1) { 62 | $contentType = $this->message->getContentType(); 63 | if (strpos($contentType, "text/html") === false) { 64 | $this->message->setContentType("text/html; charset=utf-8"); 65 | } 66 | 67 | for ($i = 1; $i < count($images); $i++) { 68 | $parts = explode(">", $images[$i], 2); 69 | 70 | $src = explode("src=", $parts[0], 2); 71 | $splitBy = $src[1][0]; 72 | 73 | $data = explode($splitBy, $src[1], 3); 74 | 75 | // check if it is a data image 76 | if (strpos($data[1], "data") === 0) { 77 | if (strpos($data[1], "data:image") === 0) { 78 | // data image 79 | $embed = $this->embedDataImage($data[1]); 80 | } else { 81 | // Not valid data image object, ignore it 82 | $images[$i] = "" . $parts[1]; 83 | continue; 84 | } 85 | } else { 86 | $url = parse_url($data[1]); 87 | if (isset($url['host']) && !empty($url['host'])) { 88 | $embed = $this->embedRemoteImage($data[1]); 89 | } else { 90 | $embed = $this->embedLocalImage($data[1]); 91 | } 92 | } 93 | $img = ""; 94 | 95 | 96 | $images[$i] = $img . $parts[1]; 97 | } 98 | 99 | $this->message->setBody(implode("", $images)); 100 | } 101 | } 102 | 103 | protected function embedLocalImage($src) 104 | { 105 | // Relative path attachments 106 | if (substr($src, 0, 1) == '/' && !file_exists($src)) { 107 | if (function_exists('public_path')) { 108 | // Laravel-only, public path can be found from any sapi: 109 | $src = public_path($src); 110 | } elseif (php_sapi_name() !== 'cli' || preg_match('#phpunit$#', $_SERVER['SCRIPT_FILENAME'])) { 111 | // Standalone script; only from web: 112 | $src = $_SERVER['DOCUMENT_ROOT'] . '/' . $src; 113 | } 114 | } 115 | 116 | $embed = $this->message->embed(Swift_Image::fromPath($src)); 117 | 118 | return $embed; 119 | } 120 | 121 | protected function embedRemoteImage($url) 122 | { 123 | $fileInfo = getimagesize($url); 124 | 125 | if ($fileInfo && isset($fileInfo['mime'])) { 126 | if (strpos("image", $fileInfo['mime'] === 0)) { 127 | $ext = explode("image/", $fileInfo['mime'])[1]; 128 | 129 | if ($ext == "jpeg") { 130 | $ext = "jpg"; 131 | } 132 | 133 | $name = md5(microtime() . mt_rand()) . "." . $ext; 134 | 135 | $filePath = $this->tempDir() . DIRECTORY_SEPARATOR . $name; 136 | file_put_contents($filePath, file_get_contents($url)); 137 | 138 | $url = $this->message->embed(Swift_Image::fromPath($filePath)); 139 | } 140 | } 141 | 142 | return $url; 143 | } 144 | 145 | protected function embedDataImage($data) 146 | { 147 | // data:image/type;base64, 148 | $data = explode(";base64,", $data, 2); 149 | 150 | $ext = explode("image/", $data[0])[1]; 151 | 152 | if ($ext == "jpeg") { 153 | $ext = "jpg"; 154 | } 155 | 156 | $name = md5(microtime() . mt_rand()) . "." . $ext; 157 | 158 | $filePath = $this->tempDir() . DIRECTORY_SEPARATOR . $name; 159 | file_put_contents($filePath, base64_decode($data[1])); 160 | 161 | $embed = $this->message->embed(Swift_Image::fromPath($filePath)); 162 | 163 | $this->tempFiles[] = $filePath; 164 | 165 | return $embed; 166 | } 167 | 168 | protected function tempDir() 169 | { 170 | return ini_get('upload_tmp_dir') ?: sys_get_temp_dir(); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /tests/EmbedImagesTest.php: -------------------------------------------------------------------------------- 1 | mailer = new Swift_Mailer($transporter); 23 | 24 | $this->mock = $this->getMockBuilder(\Puz\Mail\AutoEmbed\ImagesToAttachments::class) 25 | ->setMethods(array('sendPerformed')) 26 | ->getMock(); 27 | 28 | $this->mailer->registerPlugin($this->mock); 29 | } 30 | 31 | public function tearDown() 32 | { 33 | $reflector = new ReflectionClass(\Puz\Mail\AutoEmbed\ImagesToAttachments::class); 34 | $property = $reflector->getProperty("tempFiles"); 35 | $property->setAccessible(true); 36 | 37 | /** @var array $files */ 38 | $files = $property->getValue($this->mock); 39 | 40 | foreach ($files as $file) { 41 | unlink($file); 42 | } 43 | } 44 | 45 | /** 46 | * @test 47 | */ 48 | public function can_embed_local_image_relative_path_without_laravel() 49 | { 50 | $imageFile = "/data/smallimage.png"; 51 | $_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__); 52 | 53 | $bodyBefore = ""; 54 | $message = new Swift_Message("Test", $bodyBefore); 55 | 56 | $this->mailer->send($message); 57 | 58 | 59 | $bodyAfter = $message->getBody(); 60 | $this->assertNotEquals($bodyBefore, $bodyAfter, "Image was not inline embedded"); 61 | 62 | $this->assertRegExp("/"; 87 | $message = new Swift_Message("Test", $bodyBefore); 88 | 89 | $this->mailer->send($message); 90 | 91 | 92 | $bodyAfter = $message->getBody(); 93 | $this->assertNotEquals($bodyBefore, $bodyAfter, "Image was not inline embedded"); 94 | 95 | $this->assertRegExp("/"; 115 | $message = new Swift_Message("Test", $bodyBefore); 116 | 117 | $this->mailer->send($message); 118 | 119 | 120 | $bodyAfter = $message->getBody(); 121 | $this->assertNotEquals($bodyBefore, $bodyAfter, "Image was not inline embedded"); 122 | 123 | $this->assertRegExp("/"; 144 | $message = new Swift_Message("Test", $bodyBefore); 145 | 146 | $this->mailer->send($message); 147 | 148 | $bodyAfter = $message->getBody(); 149 | $this->assertNotEquals($bodyBefore, $bodyAfter, "Image was not inline embedded"); 150 | 151 | $this->assertRegExp("/assertContains("Content-Type: image/png; name=", $messageContent); 156 | $this->assertContains("Content-Transfer-Encoding: base64", $messageContent); 157 | $this->assertContains("Content-Disposition: inline; filename=", $messageContent); 158 | 159 | $oneLineContent = preg_replace("/\n|\r/", "", $messageContent); 160 | $this->assertContains($base64, $oneLineContent); 161 | } 162 | 163 | /** 164 | * @test 165 | */ 166 | public function can_embed_base64_jpeg_image() 167 | { 168 | $base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY3growIAAycBLhVrvukAAAAASUVORK5CYII="; 169 | $imageFile = "data:image/jpeg;base64,$base64"; 170 | 171 | $bodyBefore = ""; 172 | $message = new Swift_Message("Test", $bodyBefore); 173 | 174 | $this->mailer->send($message); 175 | 176 | $bodyAfter = $message->getBody(); 177 | $this->assertNotEquals($bodyBefore, $bodyAfter, "Image was not inline embedded"); 178 | 179 | $this->assertRegExp("/assertRegExp("/Content-Type: image\/jpeg; name=.*(?=\.jpg)/", $messageContent); 183 | $this->assertContains("Content-Transfer-Encoding: base64", $messageContent); 184 | $this->assertContains("Content-Disposition: inline; filename=", $messageContent); 185 | 186 | $oneLineContent = preg_replace("/\n|\r/", "", $messageContent); 187 | $this->assertContains($base64, $oneLineContent); 188 | } 189 | 190 | /** 191 | * @test 192 | */ 193 | public function can_embed_remote_image() 194 | { 195 | // TODO: Find a way to start built-in web server while running tests 196 | // $imageFile = "http://localhost:1338/data/smallimage.png"; 197 | // 198 | // $bodyBefore = ""; 199 | // $message = new Swift_Message("Test", $bodyBefore); 200 | // 201 | // $this->mailer->send($message); 202 | // 203 | // 204 | // $bodyAfter = $message->getBody(); 205 | // $this->assertNotEquals($bodyBefore, $bodyAfter, "Image was not inline embedded"); 206 | // 207 | // $this->assertRegExp("/"; 230 | $message = new Swift_Message("Test", $bodyBefore); 231 | 232 | $this->mailer->send($message); 233 | 234 | $bodyAfter = $message->getBody(); 235 | $this->assertEquals($bodyBefore, $bodyAfter, "Image was inline embedded"); 236 | 237 | $this->assertNotRegExp("/=5.3.3", 804 | "phpspec/prophecy": "^1.3.1", 805 | "phpunit/php-code-coverage": "~2.1", 806 | "phpunit/php-file-iterator": "~1.4", 807 | "phpunit/php-text-template": "~1.2", 808 | "phpunit/php-timer": "^1.0.6", 809 | "phpunit/phpunit-mock-objects": "~2.3", 810 | "sebastian/comparator": "~1.1", 811 | "sebastian/diff": "~1.2", 812 | "sebastian/environment": "~1.3", 813 | "sebastian/exporter": "~1.2", 814 | "sebastian/global-state": "~1.0", 815 | "sebastian/version": "~1.0", 816 | "symfony/yaml": "~2.1|~3.0" 817 | }, 818 | "suggest": { 819 | "phpunit/php-invoker": "~1.1" 820 | }, 821 | "bin": [ 822 | "phpunit" 823 | ], 824 | "type": "library", 825 | "extra": { 826 | "branch-alias": { 827 | "dev-master": "4.8.x-dev" 828 | } 829 | }, 830 | "autoload": { 831 | "classmap": [ 832 | "src/" 833 | ] 834 | }, 835 | "notification-url": "https://packagist.org/downloads/", 836 | "license": [ 837 | "BSD-3-Clause" 838 | ], 839 | "authors": [ 840 | { 841 | "name": "Sebastian Bergmann", 842 | "email": "sebastian@phpunit.de", 843 | "role": "lead" 844 | } 845 | ], 846 | "description": "The PHP Unit Testing framework.", 847 | "homepage": "https://phpunit.de/", 848 | "keywords": [ 849 | "phpunit", 850 | "testing", 851 | "xunit" 852 | ], 853 | "time": "2016-05-17 03:09:28" 854 | }, 855 | { 856 | "name": "phpunit/phpunit-mock-objects", 857 | "version": "2.3.8", 858 | "source": { 859 | "type": "git", 860 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 861 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 862 | }, 863 | "dist": { 864 | "type": "zip", 865 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 866 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 867 | "shasum": "" 868 | }, 869 | "require": { 870 | "doctrine/instantiator": "^1.0.2", 871 | "php": ">=5.3.3", 872 | "phpunit/php-text-template": "~1.2", 873 | "sebastian/exporter": "~1.2" 874 | }, 875 | "require-dev": { 876 | "phpunit/phpunit": "~4.4" 877 | }, 878 | "suggest": { 879 | "ext-soap": "*" 880 | }, 881 | "type": "library", 882 | "extra": { 883 | "branch-alias": { 884 | "dev-master": "2.3.x-dev" 885 | } 886 | }, 887 | "autoload": { 888 | "classmap": [ 889 | "src/" 890 | ] 891 | }, 892 | "notification-url": "https://packagist.org/downloads/", 893 | "license": [ 894 | "BSD-3-Clause" 895 | ], 896 | "authors": [ 897 | { 898 | "name": "Sebastian Bergmann", 899 | "email": "sb@sebastian-bergmann.de", 900 | "role": "lead" 901 | } 902 | ], 903 | "description": "Mock Object library for PHPUnit", 904 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 905 | "keywords": [ 906 | "mock", 907 | "xunit" 908 | ], 909 | "time": "2015-10-02 06:51:40" 910 | }, 911 | { 912 | "name": "sebastian/comparator", 913 | "version": "1.2.0", 914 | "source": { 915 | "type": "git", 916 | "url": "https://github.com/sebastianbergmann/comparator.git", 917 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 918 | }, 919 | "dist": { 920 | "type": "zip", 921 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 922 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 923 | "shasum": "" 924 | }, 925 | "require": { 926 | "php": ">=5.3.3", 927 | "sebastian/diff": "~1.2", 928 | "sebastian/exporter": "~1.2" 929 | }, 930 | "require-dev": { 931 | "phpunit/phpunit": "~4.4" 932 | }, 933 | "type": "library", 934 | "extra": { 935 | "branch-alias": { 936 | "dev-master": "1.2.x-dev" 937 | } 938 | }, 939 | "autoload": { 940 | "classmap": [ 941 | "src/" 942 | ] 943 | }, 944 | "notification-url": "https://packagist.org/downloads/", 945 | "license": [ 946 | "BSD-3-Clause" 947 | ], 948 | "authors": [ 949 | { 950 | "name": "Jeff Welch", 951 | "email": "whatthejeff@gmail.com" 952 | }, 953 | { 954 | "name": "Volker Dusch", 955 | "email": "github@wallbash.com" 956 | }, 957 | { 958 | "name": "Bernhard Schussek", 959 | "email": "bschussek@2bepublished.at" 960 | }, 961 | { 962 | "name": "Sebastian Bergmann", 963 | "email": "sebastian@phpunit.de" 964 | } 965 | ], 966 | "description": "Provides the functionality to compare PHP values for equality", 967 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 968 | "keywords": [ 969 | "comparator", 970 | "compare", 971 | "equality" 972 | ], 973 | "time": "2015-07-26 15:48:44" 974 | }, 975 | { 976 | "name": "sebastian/diff", 977 | "version": "1.4.1", 978 | "source": { 979 | "type": "git", 980 | "url": "https://github.com/sebastianbergmann/diff.git", 981 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 982 | }, 983 | "dist": { 984 | "type": "zip", 985 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 986 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 987 | "shasum": "" 988 | }, 989 | "require": { 990 | "php": ">=5.3.3" 991 | }, 992 | "require-dev": { 993 | "phpunit/phpunit": "~4.8" 994 | }, 995 | "type": "library", 996 | "extra": { 997 | "branch-alias": { 998 | "dev-master": "1.4-dev" 999 | } 1000 | }, 1001 | "autoload": { 1002 | "classmap": [ 1003 | "src/" 1004 | ] 1005 | }, 1006 | "notification-url": "https://packagist.org/downloads/", 1007 | "license": [ 1008 | "BSD-3-Clause" 1009 | ], 1010 | "authors": [ 1011 | { 1012 | "name": "Kore Nordmann", 1013 | "email": "mail@kore-nordmann.de" 1014 | }, 1015 | { 1016 | "name": "Sebastian Bergmann", 1017 | "email": "sebastian@phpunit.de" 1018 | } 1019 | ], 1020 | "description": "Diff implementation", 1021 | "homepage": "https://github.com/sebastianbergmann/diff", 1022 | "keywords": [ 1023 | "diff" 1024 | ], 1025 | "time": "2015-12-08 07:14:41" 1026 | }, 1027 | { 1028 | "name": "sebastian/environment", 1029 | "version": "1.3.7", 1030 | "source": { 1031 | "type": "git", 1032 | "url": "https://github.com/sebastianbergmann/environment.git", 1033 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" 1034 | }, 1035 | "dist": { 1036 | "type": "zip", 1037 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", 1038 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", 1039 | "shasum": "" 1040 | }, 1041 | "require": { 1042 | "php": ">=5.3.3" 1043 | }, 1044 | "require-dev": { 1045 | "phpunit/phpunit": "~4.4" 1046 | }, 1047 | "type": "library", 1048 | "extra": { 1049 | "branch-alias": { 1050 | "dev-master": "1.3.x-dev" 1051 | } 1052 | }, 1053 | "autoload": { 1054 | "classmap": [ 1055 | "src/" 1056 | ] 1057 | }, 1058 | "notification-url": "https://packagist.org/downloads/", 1059 | "license": [ 1060 | "BSD-3-Clause" 1061 | ], 1062 | "authors": [ 1063 | { 1064 | "name": "Sebastian Bergmann", 1065 | "email": "sebastian@phpunit.de" 1066 | } 1067 | ], 1068 | "description": "Provides functionality to handle HHVM/PHP environments", 1069 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1070 | "keywords": [ 1071 | "Xdebug", 1072 | "environment", 1073 | "hhvm" 1074 | ], 1075 | "time": "2016-05-17 03:18:57" 1076 | }, 1077 | { 1078 | "name": "sebastian/exporter", 1079 | "version": "1.2.2", 1080 | "source": { 1081 | "type": "git", 1082 | "url": "https://github.com/sebastianbergmann/exporter.git", 1083 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 1084 | }, 1085 | "dist": { 1086 | "type": "zip", 1087 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 1088 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 1089 | "shasum": "" 1090 | }, 1091 | "require": { 1092 | "php": ">=5.3.3", 1093 | "sebastian/recursion-context": "~1.0" 1094 | }, 1095 | "require-dev": { 1096 | "ext-mbstring": "*", 1097 | "phpunit/phpunit": "~4.4" 1098 | }, 1099 | "type": "library", 1100 | "extra": { 1101 | "branch-alias": { 1102 | "dev-master": "1.3.x-dev" 1103 | } 1104 | }, 1105 | "autoload": { 1106 | "classmap": [ 1107 | "src/" 1108 | ] 1109 | }, 1110 | "notification-url": "https://packagist.org/downloads/", 1111 | "license": [ 1112 | "BSD-3-Clause" 1113 | ], 1114 | "authors": [ 1115 | { 1116 | "name": "Jeff Welch", 1117 | "email": "whatthejeff@gmail.com" 1118 | }, 1119 | { 1120 | "name": "Volker Dusch", 1121 | "email": "github@wallbash.com" 1122 | }, 1123 | { 1124 | "name": "Bernhard Schussek", 1125 | "email": "bschussek@2bepublished.at" 1126 | }, 1127 | { 1128 | "name": "Sebastian Bergmann", 1129 | "email": "sebastian@phpunit.de" 1130 | }, 1131 | { 1132 | "name": "Adam Harvey", 1133 | "email": "aharvey@php.net" 1134 | } 1135 | ], 1136 | "description": "Provides the functionality to export PHP variables for visualization", 1137 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1138 | "keywords": [ 1139 | "export", 1140 | "exporter" 1141 | ], 1142 | "time": "2016-06-17 09:04:28" 1143 | }, 1144 | { 1145 | "name": "sebastian/global-state", 1146 | "version": "1.1.1", 1147 | "source": { 1148 | "type": "git", 1149 | "url": "https://github.com/sebastianbergmann/global-state.git", 1150 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1151 | }, 1152 | "dist": { 1153 | "type": "zip", 1154 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1155 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1156 | "shasum": "" 1157 | }, 1158 | "require": { 1159 | "php": ">=5.3.3" 1160 | }, 1161 | "require-dev": { 1162 | "phpunit/phpunit": "~4.2" 1163 | }, 1164 | "suggest": { 1165 | "ext-uopz": "*" 1166 | }, 1167 | "type": "library", 1168 | "extra": { 1169 | "branch-alias": { 1170 | "dev-master": "1.0-dev" 1171 | } 1172 | }, 1173 | "autoload": { 1174 | "classmap": [ 1175 | "src/" 1176 | ] 1177 | }, 1178 | "notification-url": "https://packagist.org/downloads/", 1179 | "license": [ 1180 | "BSD-3-Clause" 1181 | ], 1182 | "authors": [ 1183 | { 1184 | "name": "Sebastian Bergmann", 1185 | "email": "sebastian@phpunit.de" 1186 | } 1187 | ], 1188 | "description": "Snapshotting of global state", 1189 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1190 | "keywords": [ 1191 | "global state" 1192 | ], 1193 | "time": "2015-10-12 03:26:01" 1194 | }, 1195 | { 1196 | "name": "sebastian/recursion-context", 1197 | "version": "1.0.2", 1198 | "source": { 1199 | "type": "git", 1200 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1201 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791" 1202 | }, 1203 | "dist": { 1204 | "type": "zip", 1205 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", 1206 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791", 1207 | "shasum": "" 1208 | }, 1209 | "require": { 1210 | "php": ">=5.3.3" 1211 | }, 1212 | "require-dev": { 1213 | "phpunit/phpunit": "~4.4" 1214 | }, 1215 | "type": "library", 1216 | "extra": { 1217 | "branch-alias": { 1218 | "dev-master": "1.0.x-dev" 1219 | } 1220 | }, 1221 | "autoload": { 1222 | "classmap": [ 1223 | "src/" 1224 | ] 1225 | }, 1226 | "notification-url": "https://packagist.org/downloads/", 1227 | "license": [ 1228 | "BSD-3-Clause" 1229 | ], 1230 | "authors": [ 1231 | { 1232 | "name": "Jeff Welch", 1233 | "email": "whatthejeff@gmail.com" 1234 | }, 1235 | { 1236 | "name": "Sebastian Bergmann", 1237 | "email": "sebastian@phpunit.de" 1238 | }, 1239 | { 1240 | "name": "Adam Harvey", 1241 | "email": "aharvey@php.net" 1242 | } 1243 | ], 1244 | "description": "Provides functionality to recursively process PHP variables", 1245 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1246 | "time": "2015-11-11 19:50:13" 1247 | }, 1248 | { 1249 | "name": "sebastian/version", 1250 | "version": "1.0.6", 1251 | "source": { 1252 | "type": "git", 1253 | "url": "https://github.com/sebastianbergmann/version.git", 1254 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 1255 | }, 1256 | "dist": { 1257 | "type": "zip", 1258 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1259 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1260 | "shasum": "" 1261 | }, 1262 | "type": "library", 1263 | "autoload": { 1264 | "classmap": [ 1265 | "src/" 1266 | ] 1267 | }, 1268 | "notification-url": "https://packagist.org/downloads/", 1269 | "license": [ 1270 | "BSD-3-Clause" 1271 | ], 1272 | "authors": [ 1273 | { 1274 | "name": "Sebastian Bergmann", 1275 | "email": "sebastian@phpunit.de", 1276 | "role": "lead" 1277 | } 1278 | ], 1279 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1280 | "homepage": "https://github.com/sebastianbergmann/version", 1281 | "time": "2015-06-21 13:59:46" 1282 | }, 1283 | { 1284 | "name": "symfony/yaml", 1285 | "version": "v3.1.2", 1286 | "source": { 1287 | "type": "git", 1288 | "url": "https://github.com/symfony/yaml.git", 1289 | "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de" 1290 | }, 1291 | "dist": { 1292 | "type": "zip", 1293 | "url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de", 1294 | "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de", 1295 | "shasum": "" 1296 | }, 1297 | "require": { 1298 | "php": ">=5.5.9" 1299 | }, 1300 | "type": "library", 1301 | "extra": { 1302 | "branch-alias": { 1303 | "dev-master": "3.1-dev" 1304 | } 1305 | }, 1306 | "autoload": { 1307 | "psr-4": { 1308 | "Symfony\\Component\\Yaml\\": "" 1309 | }, 1310 | "exclude-from-classmap": [ 1311 | "/Tests/" 1312 | ] 1313 | }, 1314 | "notification-url": "https://packagist.org/downloads/", 1315 | "license": [ 1316 | "MIT" 1317 | ], 1318 | "authors": [ 1319 | { 1320 | "name": "Fabien Potencier", 1321 | "email": "fabien@symfony.com" 1322 | }, 1323 | { 1324 | "name": "Symfony Community", 1325 | "homepage": "https://symfony.com/contributors" 1326 | } 1327 | ], 1328 | "description": "Symfony Yaml Component", 1329 | "homepage": "https://symfony.com", 1330 | "time": "2016-06-29 05:41:56" 1331 | }, 1332 | { 1333 | "name": "webmozart/assert", 1334 | "version": "1.0.2", 1335 | "source": { 1336 | "type": "git", 1337 | "url": "https://github.com/webmozart/assert.git", 1338 | "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" 1339 | }, 1340 | "dist": { 1341 | "type": "zip", 1342 | "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", 1343 | "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", 1344 | "shasum": "" 1345 | }, 1346 | "require": { 1347 | "php": ">=5.3.3" 1348 | }, 1349 | "require-dev": { 1350 | "phpunit/phpunit": "^4.6" 1351 | }, 1352 | "type": "library", 1353 | "extra": { 1354 | "branch-alias": { 1355 | "dev-master": "1.0-dev" 1356 | } 1357 | }, 1358 | "autoload": { 1359 | "psr-4": { 1360 | "Webmozart\\Assert\\": "src/" 1361 | } 1362 | }, 1363 | "notification-url": "https://packagist.org/downloads/", 1364 | "license": [ 1365 | "MIT" 1366 | ], 1367 | "authors": [ 1368 | { 1369 | "name": "Bernhard Schussek", 1370 | "email": "bschussek@gmail.com" 1371 | } 1372 | ], 1373 | "description": "Assertions to validate method input/output with nice error messages.", 1374 | "keywords": [ 1375 | "assert", 1376 | "check", 1377 | "validate" 1378 | ], 1379 | "time": "2015-08-24 13:29:44" 1380 | } 1381 | ], 1382 | "aliases": [], 1383 | "minimum-stability": "stable", 1384 | "stability-flags": [], 1385 | "prefer-stable": false, 1386 | "prefer-lowest": false, 1387 | "platform": [], 1388 | "platform-dev": [] 1389 | } 1390 | --------------------------------------------------------------------------------