aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--composer.json17
-rw-r--r--composer.lock708
-rw-r--r--src/Wallabag/ApiBundle/Controller/WallabagRestController.php10
-rw-r--r--src/Wallabag/CoreBundle/Controller/EntryController.php6
-rw-r--r--src/Wallabag/CoreBundle/Entity/Entry.php31
-rw-r--r--src/Wallabag/CoreBundle/Helper/Content.php34
-rw-r--r--src/Wallabag/CoreBundle/Helper/ContentProxy.php60
-rw-r--r--src/Wallabag/CoreBundle/Helper/Url.php28
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml10
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig4
-rw-r--r--src/Wallabag/CoreBundle/Service/Extractor.php96
-rw-r--r--src/Wallabag/CoreBundle/Tests/Helper/ContentProxyTest.php84
12 files changed, 730 insertions, 358 deletions
diff --git a/composer.json b/composer.json
index 2c5111fd..20bb5537 100644
--- a/composer.json
+++ b/composer.json
@@ -27,20 +27,10 @@
27 "email": "hello@wallabag.org", 27 "email": "hello@wallabag.org",
28 "issues": "https://github.com/wallabag/wallabag/issues" 28 "issues": "https://github.com/wallabag/wallabag/issues"
29 }, 29 },
30 "repositories": [
31 {
32 "type": "vcs",
33 "url": "https://github.com/wallabag/php-readability"
34 },
35 {
36 "type": "vcs",
37 "url": "https://github.com/wallabag/Fivefilters_Libraries"
38 }
39 ],
40 "require": { 30 "require": {
41 "php": ">=5.3.3", 31 "php": ">=5.3.3",
42 "symfony/symfony": "~2.7.0", 32 "symfony/symfony": "~2.7.0",
43 "doctrine/orm": "~2.2,>=2.2.3", 33 "doctrine/orm": "~2.3",
44 "doctrine/doctrine-bundle": "~1.2", 34 "doctrine/doctrine-bundle": "~1.2",
45 "twig/extensions": "~1.0", 35 "twig/extensions": "~1.0",
46 "symfony/assetic-bundle": "~2.3", 36 "symfony/assetic-bundle": "~2.3",
@@ -60,10 +50,9 @@
60 "willdurand/hateoas-bundle": "~0.5.0", 50 "willdurand/hateoas-bundle": "~0.5.0",
61 "htmlawed/htmlawed": "~1.1.19", 51 "htmlawed/htmlawed": "~1.1.19",
62 "liip/theme-bundle": "~1.1.3", 52 "liip/theme-bundle": "~1.1.3",
63 "wallabag/php-readability": "~1.0.0",
64 "wallabag/Fivefilters_Libraries": "~1.0",
65 "pagerfanta/pagerfanta": "~1.0.3", 53 "pagerfanta/pagerfanta": "~1.0.3",
66 "lexik/form-filter-bundle": "~4.0" 54 "lexik/form-filter-bundle": "~4.0",
55 "j0k3r/graby": "~1.0"
67 }, 56 },
68 "require-dev": { 57 "require-dev": {
69 "doctrine/doctrine-fixtures-bundle": "~2.2.0", 58 "doctrine/doctrine-fixtures-bundle": "~2.2.0",
diff --git a/composer.lock b/composer.lock
index 559a08dc..35d8b978 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 "This file is @generated automatically" 5 "This file is @generated automatically"
6 ], 6 ],
7 "hash": "52545aca8a752dfc2969d6cb9f0cb8d3", 7 "hash": "f5520667cebcae76568ff448172854bd",
8 "packages": [ 8 "packages": [
9 { 9 {
10 "name": "doctrine/annotations", 10 "name": "doctrine/annotations",
11 "version": "v1.2.6", 11 "version": "v1.2.7",
12 "source": { 12 "source": {
13 "type": "git", 13 "type": "git",
14 "url": "https://github.com/doctrine/annotations.git", 14 "url": "https://github.com/doctrine/annotations.git",
15 "reference": "f4a91702ca3cd2e568c3736aa031ed00c3752af4" 15 "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535"
16 }, 16 },
17 "dist": { 17 "dist": {
18 "type": "zip", 18 "type": "zip",
19 "url": "https://api.github.com/repos/doctrine/annotations/zipball/f4a91702ca3cd2e568c3736aa031ed00c3752af4", 19 "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
20 "reference": "f4a91702ca3cd2e568c3736aa031ed00c3752af4", 20 "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
21 "shasum": "" 21 "shasum": ""
22 }, 22 },
23 "require": { 23 "require": {
@@ -72,20 +72,20 @@
72 "docblock", 72 "docblock",
73 "parser" 73 "parser"
74 ], 74 ],
75 "time": "2015-06-17 12:21:22" 75 "time": "2015-08-31 12:32:49"
76 }, 76 },
77 { 77 {
78 "name": "doctrine/cache", 78 "name": "doctrine/cache",
79 "version": "v1.4.1", 79 "version": "v1.4.2",
80 "source": { 80 "source": {
81 "type": "git", 81 "type": "git",
82 "url": "https://github.com/doctrine/cache.git", 82 "url": "https://github.com/doctrine/cache.git",
83 "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03" 83 "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca"
84 }, 84 },
85 "dist": { 85 "dist": {
86 "type": "zip", 86 "type": "zip",
87 "url": "https://api.github.com/repos/doctrine/cache/zipball/c9eadeb743ac6199f7eec423cb9426bc518b7b03", 87 "url": "https://api.github.com/repos/doctrine/cache/zipball/8c434000f420ade76a07c64cbe08ca47e5c101ca",
88 "reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03", 88 "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca",
89 "shasum": "" 89 "shasum": ""
90 }, 90 },
91 "require": { 91 "require": {
@@ -142,7 +142,7 @@
142 "cache", 142 "cache",
143 "caching" 143 "caching"
144 ], 144 ],
145 "time": "2015-04-15 00:11:59" 145 "time": "2015-08-31 12:36:41"
146 }, 146 },
147 { 147 {
148 "name": "doctrine/collections", 148 "name": "doctrine/collections",
@@ -212,16 +212,16 @@
212 }, 212 },
213 { 213 {
214 "name": "doctrine/common", 214 "name": "doctrine/common",
215 "version": "v2.5.0", 215 "version": "v2.5.1",
216 "source": { 216 "source": {
217 "type": "git", 217 "type": "git",
218 "url": "https://github.com/doctrine/common.git", 218 "url": "https://github.com/doctrine/common.git",
219 "reference": "cd8daf2501e10c63dced7b8b9b905844316ae9d3" 219 "reference": "0009b8f0d4a917aabc971fb089eba80e872f83f9"
220 }, 220 },
221 "dist": { 221 "dist": {
222 "type": "zip", 222 "type": "zip",
223 "url": "https://api.github.com/repos/doctrine/common/zipball/cd8daf2501e10c63dced7b8b9b905844316ae9d3", 223 "url": "https://api.github.com/repos/doctrine/common/zipball/0009b8f0d4a917aabc971fb089eba80e872f83f9",
224 "reference": "cd8daf2501e10c63dced7b8b9b905844316ae9d3", 224 "reference": "0009b8f0d4a917aabc971fb089eba80e872f83f9",
225 "shasum": "" 225 "shasum": ""
226 }, 226 },
227 "require": { 227 "require": {
@@ -281,7 +281,7 @@
281 "persistence", 281 "persistence",
282 "spl" 282 "spl"
283 ], 283 ],
284 "time": "2015-04-02 19:55:44" 284 "time": "2015-08-31 13:00:22"
285 }, 285 },
286 { 286 {
287 "name": "doctrine/dbal", 287 "name": "doctrine/dbal",
@@ -693,16 +693,16 @@
693 }, 693 },
694 { 694 {
695 "name": "doctrine/orm", 695 "name": "doctrine/orm",
696 "version": "v2.5.0", 696 "version": "v2.5.1",
697 "source": { 697 "source": {
698 "type": "git", 698 "type": "git",
699 "url": "https://github.com/doctrine/doctrine2.git", 699 "url": "https://github.com/doctrine/doctrine2.git",
700 "reference": "aa80c7d2c55a372f5f9f825f5c66dbda53a6e3fe" 700 "reference": "e6a83bedbe67579cb0bfb688e982e617943a2945"
701 }, 701 },
702 "dist": { 702 "dist": {
703 "type": "zip", 703 "type": "zip",
704 "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/aa80c7d2c55a372f5f9f825f5c66dbda53a6e3fe", 704 "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/e6a83bedbe67579cb0bfb688e982e617943a2945",
705 "reference": "aa80c7d2c55a372f5f9f825f5c66dbda53a6e3fe", 705 "reference": "e6a83bedbe67579cb0bfb688e982e617943a2945",
706 "shasum": "" 706 "shasum": ""
707 }, 707 },
708 "require": { 708 "require": {
@@ -766,7 +766,7 @@
766 "database", 766 "database",
767 "orm" 767 "orm"
768 ], 768 ],
769 "time": "2015-04-02 20:40:18" 769 "time": "2015-08-31 12:59:39"
770 }, 770 },
771 { 771 {
772 "name": "ezyang/htmlpurifier", 772 "name": "ezyang/htmlpurifier",
@@ -813,6 +813,52 @@
813 "time": "2015-08-05 01:03:42" 813 "time": "2015-08-05 01:03:42"
814 }, 814 },
815 { 815 {
816 "name": "fin1te/safecurl",
817 "version": "v1.1",
818 "source": {
819 "type": "git",
820 "url": "https://github.com/fin1te/safecurl.git",
821 "reference": "98aae75a1f4f8dec2194ce889d418d16c3c877e4"
822 },
823 "dist": {
824 "type": "zip",
825 "url": "https://api.github.com/repos/fin1te/safecurl/zipball/98aae75a1f4f8dec2194ce889d418d16c3c877e4",
826 "reference": "98aae75a1f4f8dec2194ce889d418d16c3c877e4",
827 "shasum": ""
828 },
829 "require": {
830 "php": ">=5.3.0"
831 },
832 "require-dev": {
833 "phpunit/phpunit": "3.7.*"
834 },
835 "type": "library",
836 "autoload": {
837 "psr-0": {
838 "fin1te\\SafeCurl": "src/"
839 }
840 },
841 "notification-url": "https://packagist.org/downloads/",
842 "license": [
843 "MIT"
844 ],
845 "authors": [
846 {
847 "name": "Jack W",
848 "email": "jack@fin1te.net"
849 }
850 ],
851 "description": "A drop-in replacement for 'curl_exec', designed to prevent SSRF attacks.",
852 "keywords": [
853 "curl",
854 "safe",
855 "safecurl",
856 "ssrf",
857 "websec"
858 ],
859 "time": "2014-05-20 12:10:12"
860 },
861 {
816 "name": "friendsofsymfony/rest-bundle", 862 "name": "friendsofsymfony/rest-bundle",
817 "version": "1.7.1", 863 "version": "1.7.1",
818 "target-dir": "FOS/RestBundle", 864 "target-dir": "FOS/RestBundle",
@@ -897,6 +943,165 @@
897 "time": "2015-06-16 08:39:26" 943 "time": "2015-06-16 08:39:26"
898 }, 944 },
899 { 945 {
946 "name": "guzzlehttp/guzzle",
947 "version": "5.3.0",
948 "source": {
949 "type": "git",
950 "url": "https://github.com/guzzle/guzzle.git",
951 "reference": "f3c8c22471cb55475105c14769644a49c3262b93"
952 },
953 "dist": {
954 "type": "zip",
955 "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93",
956 "reference": "f3c8c22471cb55475105c14769644a49c3262b93",
957 "shasum": ""
958 },
959 "require": {
960 "guzzlehttp/ringphp": "^1.1",
961 "php": ">=5.4.0"
962 },
963 "require-dev": {
964 "ext-curl": "*",
965 "phpunit/phpunit": "^4.0",
966 "psr/log": "^1.0"
967 },
968 "type": "library",
969 "extra": {
970 "branch-alias": {
971 "dev-master": "5.0-dev"
972 }
973 },
974 "autoload": {
975 "psr-4": {
976 "GuzzleHttp\\": "src/"
977 }
978 },
979 "notification-url": "https://packagist.org/downloads/",
980 "license": [
981 "MIT"
982 ],
983 "authors": [
984 {
985 "name": "Michael Dowling",
986 "email": "mtdowling@gmail.com",
987 "homepage": "https://github.com/mtdowling"
988 }
989 ],
990 "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
991 "homepage": "http://guzzlephp.org/",
992 "keywords": [
993 "client",
994 "curl",
995 "framework",
996 "http",
997 "http client",
998 "rest",
999 "web service"
1000 ],
1001 "time": "2015-05-20 03:47:55"
1002 },
1003 {
1004 "name": "guzzlehttp/ringphp",
1005 "version": "1.1.0",
1006 "source": {
1007 "type": "git",
1008 "url": "https://github.com/guzzle/RingPHP.git",
1009 "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b"
1010 },
1011 "dist": {
1012 "type": "zip",
1013 "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
1014 "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b",
1015 "shasum": ""
1016 },
1017 "require": {
1018 "guzzlehttp/streams": "~3.0",
1019 "php": ">=5.4.0",
1020 "react/promise": "~2.0"
1021 },
1022 "require-dev": {
1023 "ext-curl": "*",
1024 "phpunit/phpunit": "~4.0"
1025 },
1026 "suggest": {
1027 "ext-curl": "Guzzle will use specific adapters if cURL is present"
1028 },
1029 "type": "library",
1030 "extra": {
1031 "branch-alias": {
1032 "dev-master": "1.1-dev"
1033 }
1034 },
1035 "autoload": {
1036 "psr-4": {
1037 "GuzzleHttp\\Ring\\": "src/"
1038 }
1039 },
1040 "notification-url": "https://packagist.org/downloads/",
1041 "license": [
1042 "MIT"
1043 ],
1044 "authors": [
1045 {
1046 "name": "Michael Dowling",
1047 "email": "mtdowling@gmail.com",
1048 "homepage": "https://github.com/mtdowling"
1049 }
1050 ],
1051 "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.",
1052 "time": "2015-05-20 03:37:09"
1053 },
1054 {
1055 "name": "guzzlehttp/streams",
1056 "version": "3.0.0",
1057 "source": {
1058 "type": "git",
1059 "url": "https://github.com/guzzle/streams.git",
1060 "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5"
1061 },
1062 "dist": {
1063 "type": "zip",
1064 "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
1065 "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5",
1066 "shasum": ""
1067 },
1068 "require": {
1069 "php": ">=5.4.0"
1070 },
1071 "require-dev": {
1072 "phpunit/phpunit": "~4.0"
1073 },
1074 "type": "library",
1075 "extra": {
1076 "branch-alias": {
1077 "dev-master": "3.0-dev"
1078 }
1079 },
1080 "autoload": {
1081 "psr-4": {
1082 "GuzzleHttp\\Stream\\": "src/"
1083 }
1084 },
1085 "notification-url": "https://packagist.org/downloads/",
1086 "license": [
1087 "MIT"
1088 ],
1089 "authors": [
1090 {
1091 "name": "Michael Dowling",
1092 "email": "mtdowling@gmail.com",
1093 "homepage": "https://github.com/mtdowling"
1094 }
1095 ],
1096 "description": "Provides a simple abstraction over streams of data",
1097 "homepage": "http://guzzlephp.org/",
1098 "keywords": [
1099 "Guzzle",
1100 "stream"
1101 ],
1102 "time": "2014-10-12 19:18:40"
1103 },
1104 {
900 "name": "htmlawed/htmlawed", 1105 "name": "htmlawed/htmlawed",
901 "version": "1.1.19", 1106 "version": "1.1.19",
902 "source": { 1107 "source": {
@@ -994,6 +1199,156 @@
994 "time": "2015-06-03 08:27:03" 1199 "time": "2015-06-03 08:27:03"
995 }, 1200 },
996 { 1201 {
1202 "name": "j0k3r/graby",
1203 "version": "1.0.0-alpha.0",
1204 "source": {
1205 "type": "git",
1206 "url": "https://github.com/j0k3r/graby.git",
1207 "reference": "553a5ddd35e89f37fce2275e1423cc4451c40dbf"
1208 },
1209 "dist": {
1210 "type": "zip",
1211 "url": "https://api.github.com/repos/j0k3r/graby/zipball/553a5ddd35e89f37fce2275e1423cc4451c40dbf",
1212 "reference": "553a5ddd35e89f37fce2275e1423cc4451c40dbf",
1213 "shasum": ""
1214 },
1215 "require": {
1216 "fin1te/safecurl": "~1.1",
1217 "guzzlehttp/guzzle": "^5.2.0",
1218 "htmlawed/htmlawed": "^1.1.19",
1219 "j0k3r/graby-site-config": "dev-master",
1220 "j0k3r/php-readability": "^1.0",
1221 "monolog/monolog": "^1.13.1",
1222 "neitanod/forceutf8": "^1.4",
1223 "php": ">=5.4",
1224 "simplepie/simplepie": "^1.3.1",
1225 "symfony/options-resolver": "^2.6.6"
1226 },
1227 "type": "library",
1228 "autoload": {
1229 "psr-4": {
1230 "Graby\\": "src/"
1231 }
1232 },
1233 "notification-url": "https://packagist.org/downloads/",
1234 "license": [
1235 "AGPL-3.0"
1236 ],
1237 "authors": [
1238 {
1239 "name": "Jeremy Benoist",
1240 "email": "jeremy.benoist@gmail.com",
1241 "role": "Developer"
1242 },
1243 {
1244 "name": "FiveFilters.org",
1245 "email": "fivefilters@fivefilters.org",
1246 "role": "Developer (original version)"
1247 }
1248 ],
1249 "description": "Graby helps you extract article content from web pages",
1250 "time": "2015-08-29 10:16:47"
1251 },
1252 {
1253 "name": "j0k3r/graby-site-config",
1254 "version": "dev-master",
1255 "source": {
1256 "type": "git",
1257 "url": "https://github.com/j0k3r/graby-site-config.git",
1258 "reference": "a5b3add9fcd716c86b8c4220bdbdfbc7e79dd182"
1259 },
1260 "dist": {
1261 "type": "zip",
1262 "url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/a5b3add9fcd716c86b8c4220bdbdfbc7e79dd182",
1263 "reference": "a5b3add9fcd716c86b8c4220bdbdfbc7e79dd182",
1264 "shasum": ""
1265 },
1266 "require": {
1267 "symfony/finder": "^2.6.6"
1268 },
1269 "type": "library",
1270 "autoload": {
1271 "psr-4": {
1272 "GrabySiteConfig\\SiteConfig\\": "/"
1273 }
1274 },
1275 "notification-url": "https://packagist.org/downloads/",
1276 "license": [
1277 "AGPL-3.0"
1278 ],
1279 "authors": [
1280 {
1281 "name": "Jeremy Benoist",
1282 "email": "jeremy.benoist@gmail.com"
1283 }
1284 ],
1285 "description": "Graby site config files",
1286 "time": "2015-09-10 12:13:05"
1287 },
1288 {
1289 "name": "j0k3r/php-readability",
1290 "version": "v1.0.4",
1291 "source": {
1292 "type": "git",
1293 "url": "https://github.com/j0k3r/php-readability.git",
1294 "reference": "c5a4a490e155fa20809c9bbcf3e318defbb7a261"
1295 },
1296 "dist": {
1297 "type": "zip",
1298 "url": "https://api.github.com/repos/j0k3r/php-readability/zipball/c5a4a490e155fa20809c9bbcf3e318defbb7a261",
1299 "reference": "c5a4a490e155fa20809c9bbcf3e318defbb7a261",
1300 "shasum": ""
1301 },
1302 "require": {
1303 "ext-tidy": ">=1.2",
1304 "php": ">=5.3.3"
1305 },
1306 "type": "library",
1307 "autoload": {
1308 "psr-4": {
1309 "Readability\\": "src/"
1310 }
1311 },
1312 "notification-url": "https://packagist.org/downloads/",
1313 "license": [
1314 "Apache-2.0"
1315 ],
1316 "authors": [
1317 {
1318 "name": "Keyvan Minoukadeh",
1319 "email": "keyvan@keyvan.net",
1320 "homepage": "http://keyvan.net",
1321 "role": "Developer (ported original JS code to PHP)"
1322 },
1323 {
1324 "name": "Arc90",
1325 "homepage": "http://arc90.com",
1326 "role": "Developer (original JS version)"
1327 },
1328 {
1329 "name": "Jeremy Benoist",
1330 "email": "jeremy.benoist@gmail.com",
1331 "homepage": "http://www.j0k3r.net",
1332 "role": "Developer"
1333 },
1334 {
1335 "name": "DitherSky",
1336 "homepage": "https://github.com/Dither",
1337 "role": "Developer (https://github.com/Dither/full-text-rss)"
1338 }
1339 ],
1340 "description": "Automatic article extraction from HTML",
1341 "keywords": [
1342 "article",
1343 "article extraction",
1344 "content",
1345 "content extraction",
1346 "extraction",
1347 "html"
1348 ],
1349 "time": "2015-08-24 09:10:54"
1350 },
1351 {
997 "name": "jdorn/sql-formatter", 1352 "name": "jdorn/sql-formatter",
998 "version": "v1.2.17", 1353 "version": "v1.2.17",
999 "source": { 1354 "source": {
@@ -1272,35 +1627,39 @@
1272 }, 1627 },
1273 { 1628 {
1274 "name": "kriswallsmith/assetic", 1629 "name": "kriswallsmith/assetic",
1275 "version": "v1.2.1", 1630 "version": "v1.3.0",
1276 "source": { 1631 "source": {
1277 "type": "git", 1632 "type": "git",
1278 "url": "https://github.com/kriswallsmith/assetic.git", 1633 "url": "https://github.com/kriswallsmith/assetic.git",
1279 "reference": "b20efe38845d20458702f97f3ff625d80805897b" 1634 "reference": "56cb5d6dec9e7a68a4da2fa89844f39d41092f31"
1280 }, 1635 },
1281 "dist": { 1636 "dist": {
1282 "type": "zip", 1637 "type": "zip",
1283 "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/b20efe38845d20458702f97f3ff625d80805897b", 1638 "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/56cb5d6dec9e7a68a4da2fa89844f39d41092f31",
1284 "reference": "b20efe38845d20458702f97f3ff625d80805897b", 1639 "reference": "56cb5d6dec9e7a68a4da2fa89844f39d41092f31",
1285 "shasum": "" 1640 "shasum": ""
1286 }, 1641 },
1287 "require": { 1642 "require": {
1288 "php": ">=5.3.1", 1643 "php": ">=5.3.1",
1289 "symfony/process": "~2.1" 1644 "symfony/process": "~2.1"
1290 }, 1645 },
1646 "conflict": {
1647 "twig/twig": "<1.12"
1648 },
1291 "require-dev": { 1649 "require-dev": {
1292 "cssmin/cssmin": "*", 1650 "cssmin/cssmin": "*",
1293 "joliclic/javascript-packer": "*", 1651 "joliclic/javascript-packer": "*",
1294 "kamicane/packager": "*", 1652 "kamicane/packager": "*",
1295 "leafo/lessphp": "*", 1653 "leafo/lessphp": "^0.3.7",
1296 "leafo/scssphp": "*", 1654 "leafo/scssphp": "*@dev",
1297 "leafo/scssphp-compass": "*", 1655 "leafo/scssphp-compass": "*@dev",
1298 "mrclay/minify": "*", 1656 "mrclay/minify": "*",
1299 "patchwork/jsqueeze": "~1.0", 1657 "patchwork/jsqueeze": "~1.0|~2.0",
1300 "phpunit/phpunit": "~4", 1658 "phpunit/phpunit": "~4.8",
1301 "psr/log": "~1.0", 1659 "psr/log": "~1.0",
1302 "ptachoire/cssembed": "*", 1660 "ptachoire/cssembed": "*",
1303 "twig/twig": "~1.6" 1661 "symfony/phpunit-bridge": "~2.7",
1662 "twig/twig": "~1.8|~2.0"
1304 }, 1663 },
1305 "suggest": { 1664 "suggest": {
1306 "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler", 1665 "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler",
@@ -1313,7 +1672,7 @@
1313 "type": "library", 1672 "type": "library",
1314 "extra": { 1673 "extra": {
1315 "branch-alias": { 1674 "branch-alias": {
1316 "dev-master": "1.2-dev" 1675 "dev-master": "1.3-dev"
1317 } 1676 }
1318 }, 1677 },
1319 "autoload": { 1678 "autoload": {
@@ -1342,7 +1701,7 @@
1342 "compression", 1701 "compression",
1343 "minification" 1702 "minification"
1344 ], 1703 ],
1345 "time": "2014-12-12 05:04:05" 1704 "time": "2015-08-31 19:07:16"
1346 }, 1705 },
1347 { 1706 {
1348 "name": "lexik/form-filter-bundle", 1707 "name": "lexik/form-filter-bundle",
@@ -1556,16 +1915,16 @@
1556 }, 1915 },
1557 { 1916 {
1558 "name": "monolog/monolog", 1917 "name": "monolog/monolog",
1559 "version": "1.16.0", 1918 "version": "1.17.1",
1560 "source": { 1919 "source": {
1561 "type": "git", 1920 "type": "git",
1562 "url": "https://github.com/Seldaek/monolog.git", 1921 "url": "https://github.com/Seldaek/monolog.git",
1563 "reference": "c0c0b4bee3aabce7182876b0d912ef2595563db7" 1922 "reference": "0524c87587ab85bc4c2d6f5b41253ccb930a5422"
1564 }, 1923 },
1565 "dist": { 1924 "dist": {
1566 "type": "zip", 1925 "type": "zip",
1567 "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c0c0b4bee3aabce7182876b0d912ef2595563db7", 1926 "url": "https://api.github.com/repos/Seldaek/monolog/zipball/0524c87587ab85bc4c2d6f5b41253ccb930a5422",
1568 "reference": "c0c0b4bee3aabce7182876b0d912ef2595563db7", 1927 "reference": "0524c87587ab85bc4c2d6f5b41253ccb930a5422",
1569 "shasum": "" 1928 "shasum": ""
1570 }, 1929 },
1571 "require": { 1930 "require": {
@@ -1582,7 +1941,7 @@
1582 "php-console/php-console": "^3.1.3", 1941 "php-console/php-console": "^3.1.3",
1583 "phpunit/phpunit": "~4.5", 1942 "phpunit/phpunit": "~4.5",
1584 "phpunit/phpunit-mock-objects": "2.3.0", 1943 "phpunit/phpunit-mock-objects": "2.3.0",
1585 "raven/raven": "~0.8", 1944 "raven/raven": "~0.11",
1586 "ruflin/elastica": ">=0.90 <3.0", 1945 "ruflin/elastica": ">=0.90 <3.0",
1587 "swiftmailer/swiftmailer": "~5.3", 1946 "swiftmailer/swiftmailer": "~5.3",
1588 "videlalvaro/php-amqplib": "~2.4" 1947 "videlalvaro/php-amqplib": "~2.4"
@@ -1628,7 +1987,41 @@
1628 "logging", 1987 "logging",
1629 "psr-3" 1988 "psr-3"
1630 ], 1989 ],
1631 "time": "2015-08-09 17:44:44" 1990 "time": "2015-08-31 09:17:37"
1991 },
1992 {
1993 "name": "neitanod/forceutf8",
1994 "version": "v1.4",
1995 "source": {
1996 "type": "git",
1997 "url": "https://github.com/neitanod/forceutf8.git",
1998 "reference": "28d50d579179abac1f6a55b03c6d9d3f6573867c"
1999 },
2000 "dist": {
2001 "type": "zip",
2002 "url": "https://api.github.com/repos/neitanod/forceutf8/zipball/28d50d579179abac1f6a55b03c6d9d3f6573867c",
2003 "reference": "28d50d579179abac1f6a55b03c6d9d3f6573867c",
2004 "shasum": ""
2005 },
2006 "require": {
2007 "php": ">=5.2.0"
2008 },
2009 "type": "library",
2010 "autoload": {
2011 "psr-0": {
2012 "ForceUTF8\\": "src/"
2013 }
2014 },
2015 "notification-url": "https://packagist.org/downloads/",
2016 "authors": [
2017 {
2018 "name": "Sebastián Grignoli",
2019 "email": "grignoli@gmail.com"
2020 }
2021 ],
2022 "description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.",
2023 "homepage": "https://github.com/neitanod/forceutf8",
2024 "time": "2014-09-24 14:59:43"
1632 }, 2025 },
1633 { 2026 {
1634 "name": "nelmio/api-doc-bundle", 2027 "name": "nelmio/api-doc-bundle",
@@ -1882,21 +2275,24 @@
1882 }, 2275 },
1883 { 2276 {
1884 "name": "phpoption/phpoption", 2277 "name": "phpoption/phpoption",
1885 "version": "1.4.0", 2278 "version": "1.5.0",
1886 "source": { 2279 "source": {
1887 "type": "git", 2280 "type": "git",
1888 "url": "https://github.com/schmittjoh/php-option.git", 2281 "url": "https://github.com/schmittjoh/php-option.git",
1889 "reference": "5d099bcf0393908bf4ad69cc47dafb785d51f7f5" 2282 "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed"
1890 }, 2283 },
1891 "dist": { 2284 "dist": {
1892 "type": "zip", 2285 "type": "zip",
1893 "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/5d099bcf0393908bf4ad69cc47dafb785d51f7f5", 2286 "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed",
1894 "reference": "5d099bcf0393908bf4ad69cc47dafb785d51f7f5", 2287 "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed",
1895 "shasum": "" 2288 "shasum": ""
1896 }, 2289 },
1897 "require": { 2290 "require": {
1898 "php": ">=5.3.0" 2291 "php": ">=5.3.0"
1899 }, 2292 },
2293 "require-dev": {
2294 "phpunit/phpunit": "4.7.*"
2295 },
1900 "type": "library", 2296 "type": "library",
1901 "extra": { 2297 "extra": {
1902 "branch-alias": { 2298 "branch-alias": {
@@ -1914,10 +2310,8 @@
1914 ], 2310 ],
1915 "authors": [ 2311 "authors": [
1916 { 2312 {
1917 "name": "Johannes Schmitt", 2313 "name": "Johannes M. Schmitt",
1918 "email": "schmittjoh@gmail.com", 2314 "email": "schmittjoh@gmail.com"
1919 "homepage": "https://github.com/schmittjoh",
1920 "role": "Developer of wrapped JMSSerializerBundle"
1921 } 2315 }
1922 ], 2316 ],
1923 "description": "Option Type for PHP", 2317 "description": "Option Type for PHP",
@@ -1927,7 +2321,7 @@
1927 "php", 2321 "php",
1928 "type" 2322 "type"
1929 ], 2323 ],
1930 "time": "2014-01-09 22:37:17" 2324 "time": "2015-07-25 16:39:46"
1931 }, 2325 },
1932 { 2326 {
1933 "name": "psr/log", 2327 "name": "psr/log",
@@ -1968,6 +2362,50 @@
1968 "time": "2012-12-21 11:40:51" 2362 "time": "2012-12-21 11:40:51"
1969 }, 2363 },
1970 { 2364 {
2365 "name": "react/promise",
2366 "version": "v2.2.1",
2367 "source": {
2368 "type": "git",
2369 "url": "https://github.com/reactphp/promise.git",
2370 "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627"
2371 },
2372 "dist": {
2373 "type": "zip",
2374 "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627",
2375 "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627",
2376 "shasum": ""
2377 },
2378 "require": {
2379 "php": ">=5.4.0"
2380 },
2381 "type": "library",
2382 "extra": {
2383 "branch-alias": {
2384 "dev-master": "2.0-dev"
2385 }
2386 },
2387 "autoload": {
2388 "psr-4": {
2389 "React\\Promise\\": "src/"
2390 },
2391 "files": [
2392 "src/functions_include.php"
2393 ]
2394 },
2395 "notification-url": "https://packagist.org/downloads/",
2396 "license": [
2397 "MIT"
2398 ],
2399 "authors": [
2400 {
2401 "name": "Jan Sorgalla",
2402 "email": "jsorgalla@gmail.com"
2403 }
2404 ],
2405 "description": "A lightweight implementation of CommonJS Promises/A for PHP",
2406 "time": "2015-07-03 13:48:55"
2407 },
2408 {
1971 "name": "sensio/distribution-bundle", 2409 "name": "sensio/distribution-bundle",
1972 "version": "v3.0.31", 2410 "version": "v3.0.31",
1973 "target-dir": "Sensio/Bundle/DistributionBundle", 2411 "target-dir": "Sensio/Bundle/DistributionBundle",
@@ -2235,32 +2673,37 @@
2235 }, 2673 },
2236 { 2674 {
2237 "name": "symfony/assetic-bundle", 2675 "name": "symfony/assetic-bundle",
2238 "version": "v2.6.1", 2676 "version": "v2.7.0",
2239 "source": { 2677 "source": {
2240 "type": "git", 2678 "type": "git",
2241 "url": "https://github.com/symfony/AsseticBundle.git", 2679 "url": "https://github.com/symfony/AsseticBundle.git",
2242 "reference": "422b0add2110f0cf9bc7a873a386ea053f4a89f0" 2680 "reference": "3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5"
2243 }, 2681 },
2244 "dist": { 2682 "dist": {
2245 "type": "zip", 2683 "type": "zip",
2246 "url": "https://api.github.com/repos/symfony/AsseticBundle/zipball/422b0add2110f0cf9bc7a873a386ea053f4a89f0", 2684 "url": "https://api.github.com/repos/symfony/AsseticBundle/zipball/3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5",
2247 "reference": "422b0add2110f0cf9bc7a873a386ea053f4a89f0", 2685 "reference": "3ae5c8ca3079b6e0033cc9fbfb6500e2bc964da5",
2248 "shasum": "" 2686 "shasum": ""
2249 }, 2687 },
2250 "require": { 2688 "require": {
2251 "kriswallsmith/assetic": "~1.2", 2689 "kriswallsmith/assetic": "~1.3",
2252 "php": ">=5.3.0", 2690 "php": ">=5.3.0",
2253 "symfony/console": "~2.3", 2691 "symfony/console": "~2.3",
2254 "symfony/dependency-injection": "~2.3", 2692 "symfony/dependency-injection": "~2.3",
2255 "symfony/framework-bundle": "~2.3", 2693 "symfony/framework-bundle": "~2.3",
2256 "symfony/yaml": "~2.3" 2694 "symfony/yaml": "~2.3"
2257 }, 2695 },
2696 "conflict": {
2697 "kriswallsmith/spork": "<=0.2",
2698 "twig/twig": "<1.20"
2699 },
2258 "require-dev": { 2700 "require-dev": {
2259 "kriswallsmith/spork": "~0.2", 2701 "kriswallsmith/spork": "~0.3",
2260 "patchwork/jsqueeze": "~1.0", 2702 "patchwork/jsqueeze": "~1.0",
2261 "symfony/class-loader": "~2.3", 2703 "symfony/class-loader": "~2.3",
2262 "symfony/css-selector": "~2.3", 2704 "symfony/css-selector": "~2.3",
2263 "symfony/dom-crawler": "~2.3", 2705 "symfony/dom-crawler": "~2.3",
2706 "symfony/phpunit-bridge": "~2.7",
2264 "symfony/twig-bundle": "~2.3" 2707 "symfony/twig-bundle": "~2.3"
2265 }, 2708 },
2266 "suggest": { 2709 "suggest": {
@@ -2270,7 +2713,7 @@
2270 "type": "symfony-bundle", 2713 "type": "symfony-bundle",
2271 "extra": { 2714 "extra": {
2272 "branch-alias": { 2715 "branch-alias": {
2273 "dev-master": "2.5-dev" 2716 "dev-master": "2.7-dev"
2274 } 2717 }
2275 }, 2718 },
2276 "autoload": { 2719 "autoload": {
@@ -2296,7 +2739,7 @@
2296 "compression", 2739 "compression",
2297 "minification" 2740 "minification"
2298 ], 2741 ],
2299 "time": "2015-01-27 12:45:16" 2742 "time": "2015-09-01 00:05:29"
2300 }, 2743 },
2301 { 2744 {
2302 "name": "symfony/monolog-bundle", 2745 "name": "symfony/monolog-bundle",
@@ -2416,23 +2859,23 @@
2416 }, 2859 },
2417 { 2860 {
2418 "name": "symfony/symfony", 2861 "name": "symfony/symfony",
2419 "version": "v2.7.3", 2862 "version": "v2.7.4",
2420 "source": { 2863 "source": {
2421 "type": "git", 2864 "type": "git",
2422 "url": "https://github.com/symfony/symfony.git", 2865 "url": "https://github.com/symfony/symfony.git",
2423 "reference": "a9af4708b4bb650c4897e9b8dfbfbdb2ea5f0486" 2866 "reference": "1fdf23fe28876844b887b0e1935c9adda43ee645"
2424 }, 2867 },
2425 "dist": { 2868 "dist": {
2426 "type": "zip", 2869 "type": "zip",
2427 "url": "https://api.github.com/repos/symfony/symfony/zipball/a9af4708b4bb650c4897e9b8dfbfbdb2ea5f0486", 2870 "url": "https://api.github.com/repos/symfony/symfony/zipball/1fdf23fe28876844b887b0e1935c9adda43ee645",
2428 "reference": "a9af4708b4bb650c4897e9b8dfbfbdb2ea5f0486", 2871 "reference": "1fdf23fe28876844b887b0e1935c9adda43ee645",
2429 "shasum": "" 2872 "shasum": ""
2430 }, 2873 },
2431 "require": { 2874 "require": {
2432 "doctrine/common": "~2.3", 2875 "doctrine/common": "~2.3",
2433 "php": ">=5.3.9", 2876 "php": ">=5.3.9",
2434 "psr/log": "~1.0", 2877 "psr/log": "~1.0",
2435 "twig/twig": "~1.18" 2878 "twig/twig": "~1.20|~2.0"
2436 }, 2879 },
2437 "replace": { 2880 "replace": {
2438 "symfony/asset": "self.version", 2881 "symfony/asset": "self.version",
@@ -2534,7 +2977,7 @@
2534 "keywords": [ 2977 "keywords": [
2535 "framework" 2978 "framework"
2536 ], 2979 ],
2537 "time": "2015-07-31 13:24:45" 2980 "time": "2015-09-08 14:26:39"
2538 }, 2981 },
2539 { 2982 {
2540 "name": "tecnick.com/tcpdf", 2983 "name": "tecnick.com/tcpdf",
@@ -2601,20 +3044,20 @@
2601 }, 3044 },
2602 { 3045 {
2603 "name": "twig/extensions", 3046 "name": "twig/extensions",
2604 "version": "v1.2.0", 3047 "version": "v1.3.0",
2605 "source": { 3048 "source": {
2606 "type": "git", 3049 "type": "git",
2607 "url": "https://github.com/twigphp/Twig-extensions.git", 3050 "url": "https://github.com/twigphp/Twig-extensions.git",
2608 "reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd" 3051 "reference": "449e3c8a9ffad7c2479c7864557275a32b037499"
2609 }, 3052 },
2610 "dist": { 3053 "dist": {
2611 "type": "zip", 3054 "type": "zip",
2612 "url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/8cf4b9fe04077bd54fc73f4fde83347040c3b8cd", 3055 "url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/449e3c8a9ffad7c2479c7864557275a32b037499",
2613 "reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd", 3056 "reference": "449e3c8a9ffad7c2479c7864557275a32b037499",
2614 "shasum": "" 3057 "shasum": ""
2615 }, 3058 },
2616 "require": { 3059 "require": {
2617 "twig/twig": "~1.12" 3060 "twig/twig": "~1.20|~2.0"
2618 }, 3061 },
2619 "require-dev": { 3062 "require-dev": {
2620 "symfony/translation": "~2.3" 3063 "symfony/translation": "~2.3"
@@ -2625,7 +3068,7 @@
2625 "type": "library", 3068 "type": "library",
2626 "extra": { 3069 "extra": {
2627 "branch-alias": { 3070 "branch-alias": {
2628 "dev-master": "1.2.x-dev" 3071 "dev-master": "1.3-dev"
2629 } 3072 }
2630 }, 3073 },
2631 "autoload": { 3074 "autoload": {
@@ -2649,29 +3092,33 @@
2649 "i18n", 3092 "i18n",
2650 "text" 3093 "text"
2651 ], 3094 ],
2652 "time": "2014-10-30 14:30:03" 3095 "time": "2015-08-22 16:38:35"
2653 }, 3096 },
2654 { 3097 {
2655 "name": "twig/twig", 3098 "name": "twig/twig",
2656 "version": "v1.20.0", 3099 "version": "v1.21.2",
2657 "source": { 3100 "source": {
2658 "type": "git", 3101 "type": "git",
2659 "url": "https://github.com/twigphp/Twig.git", 3102 "url": "https://github.com/twigphp/Twig.git",
2660 "reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844" 3103 "reference": "ddce1136beb8db29b9cd7dffa8ab518b978c9db3"
2661 }, 3104 },
2662 "dist": { 3105 "dist": {
2663 "type": "zip", 3106 "type": "zip",
2664 "url": "https://api.github.com/repos/twigphp/Twig/zipball/1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844", 3107 "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddce1136beb8db29b9cd7dffa8ab518b978c9db3",
2665 "reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844", 3108 "reference": "ddce1136beb8db29b9cd7dffa8ab518b978c9db3",
2666 "shasum": "" 3109 "shasum": ""
2667 }, 3110 },
2668 "require": { 3111 "require": {
2669 "php": ">=5.2.7" 3112 "php": ">=5.2.7"
2670 }, 3113 },
3114 "require-dev": {
3115 "symfony/debug": "~2.7",
3116 "symfony/phpunit-bridge": "~2.7"
3117 },
2671 "type": "library", 3118 "type": "library",
2672 "extra": { 3119 "extra": {
2673 "branch-alias": { 3120 "branch-alias": {
2674 "dev-master": "1.20-dev" 3121 "dev-master": "1.21-dev"
2675 } 3122 }
2676 }, 3123 },
2677 "autoload": { 3124 "autoload": {
@@ -2706,92 +3153,7 @@
2706 "keywords": [ 3153 "keywords": [
2707 "templating" 3154 "templating"
2708 ], 3155 ],
2709 "time": "2015-08-12 15:56:39" 3156 "time": "2015-09-09 05:28:51"
2710 },
2711 {
2712 "name": "wallabag/Fivefilters_Libraries",
2713 "version": "1.0.1",
2714 "source": {
2715 "type": "git",
2716 "url": "https://github.com/wallabag/Fivefilters_Libraries.git",
2717 "reference": "6a07427e07308c746e0216ed254e41e053ab3448"
2718 },
2719 "dist": {
2720 "type": "zip",
2721 "url": "https://api.github.com/repos/wallabag/Fivefilters_Libraries/zipball/6a07427e07308c746e0216ed254e41e053ab3448",
2722 "reference": "6a07427e07308c746e0216ed254e41e053ab3448",
2723 "shasum": ""
2724 },
2725 "type": "library",
2726 "authors": [
2727 {
2728 "name": "Nicolas LÅ“uillet",
2729 "email": "nicolas@loeuillet.org",
2730 "homepage": "http://www.cdetc.fr"
2731 }
2732 ],
2733 "description": "Libraries from @fivefilters.",
2734 "homepage": "https://github.com/wallabag/Fivefilters_Libraries",
2735 "support": {
2736 "source": "https://github.com/wallabag/Fivefilters_Libraries/tree/1.0.1",
2737 "issues": "https://github.com/wallabag/Fivefilters_Libraries/issues"
2738 },
2739 "time": "2015-08-14 10:11:06"
2740 },
2741 {
2742 "name": "wallabag/php-readability",
2743 "version": "v1.0",
2744 "source": {
2745 "type": "git",
2746 "url": "https://github.com/wallabag/php-readability.git",
2747 "reference": "e25182cdd1ccdebdce1149ab79c886eae1363674"
2748 },
2749 "dist": {
2750 "type": "zip",
2751 "url": "https://api.github.com/repos/wallabag/php-readability/zipball/e25182cdd1ccdebdce1149ab79c886eae1363674",
2752 "reference": "e25182cdd1ccdebdce1149ab79c886eae1363674",
2753 "shasum": ""
2754 },
2755 "require": {
2756 "php": ">=5.2"
2757 },
2758 "type": "library",
2759 "autoload": {
2760 "psr-0": {
2761 "Readability": ""
2762 }
2763 },
2764 "license": [
2765 "Apache-2.0"
2766 ],
2767 "authors": [
2768 {
2769 "name": "Keyvan Minoukadeh",
2770 "email": "keyvan@keyvan.net",
2771 "homepage": "http://keyvan.net",
2772 "role": "Developer (ported original JS code to PHP)"
2773 },
2774 {
2775 "name": "Arc90",
2776 "homepage": "http://arc90.com",
2777 "role": "Developer (original JS version)"
2778 }
2779 ],
2780 "description": "Automatic article extraction from HTML",
2781 "homepage": "http://code.fivefilters.org/php-readability/",
2782 "keywords": [
2783 "article",
2784 "article extraction",
2785 "content",
2786 "content extraction",
2787 "extraction",
2788 "html"
2789 ],
2790 "support": {
2791 "source": "https://github.com/wallabag/php-readability/tree/v1.0",
2792 "issues": "https://github.com/wallabag/php-readability/issues"
2793 },
2794 "time": "2013-04-17 13:51:09"
2795 }, 3157 },
2796 { 3158 {
2797 "name": "willdurand/hateoas", 3159 "name": "willdurand/hateoas",
@@ -2899,7 +3261,7 @@
2899 ], 3261 ],
2900 "authors": [ 3262 "authors": [
2901 { 3263 {
2902 "name": "William Durand", 3264 "name": "William DURAND",
2903 "email": "william.durand1@gmail.com" 3265 "email": "william.durand1@gmail.com"
2904 } 3266 }
2905 ], 3267 ],
@@ -2984,7 +3346,7 @@
2984 ], 3346 ],
2985 "authors": [ 3347 "authors": [
2986 { 3348 {
2987 "name": "William Durand", 3349 "name": "William DURAND",
2988 "email": "william.durand1@gmail.com" 3350 "email": "william.durand1@gmail.com"
2989 } 3351 }
2990 ], 3352 ],
@@ -3466,16 +3828,16 @@
3466 }, 3828 },
3467 { 3829 {
3468 "name": "phpunit/phpunit", 3830 "name": "phpunit/phpunit",
3469 "version": "4.8.4", 3831 "version": "4.8.6",
3470 "source": { 3832 "source": {
3471 "type": "git", 3833 "type": "git",
3472 "url": "https://github.com/sebastianbergmann/phpunit.git", 3834 "url": "https://github.com/sebastianbergmann/phpunit.git",
3473 "reference": "55bf1d6092b0e13a1f26bd5eaffeef3d8ad85ea7" 3835 "reference": "2246830f4a1a551c67933e4171bf2126dc29d357"
3474 }, 3836 },
3475 "dist": { 3837 "dist": {
3476 "type": "zip", 3838 "type": "zip",
3477 "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/55bf1d6092b0e13a1f26bd5eaffeef3d8ad85ea7", 3839 "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357",
3478 "reference": "55bf1d6092b0e13a1f26bd5eaffeef3d8ad85ea7", 3840 "reference": "2246830f4a1a551c67933e4171bf2126dc29d357",
3479 "shasum": "" 3841 "shasum": ""
3480 }, 3842 },
3481 "require": { 3843 "require": {
@@ -3534,24 +3896,24 @@
3534 "testing", 3896 "testing",
3535 "xunit" 3897 "xunit"
3536 ], 3898 ],
3537 "time": "2015-08-15 04:21:23" 3899 "time": "2015-08-24 04:09:38"
3538 }, 3900 },
3539 { 3901 {
3540 "name": "phpunit/phpunit-mock-objects", 3902 "name": "phpunit/phpunit-mock-objects",
3541 "version": "2.3.6", 3903 "version": "2.3.7",
3542 "source": { 3904 "source": {
3543 "type": "git", 3905 "type": "git",
3544 "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 3906 "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
3545 "reference": "18dfbcb81d05e2296c0bcddd4db96cade75e6f42" 3907 "reference": "5e2645ad49d196e020b85598d7c97e482725786a"
3546 }, 3908 },
3547 "dist": { 3909 "dist": {
3548 "type": "zip", 3910 "type": "zip",
3549 "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/18dfbcb81d05e2296c0bcddd4db96cade75e6f42", 3911 "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5e2645ad49d196e020b85598d7c97e482725786a",
3550 "reference": "18dfbcb81d05e2296c0bcddd4db96cade75e6f42", 3912 "reference": "5e2645ad49d196e020b85598d7c97e482725786a",
3551 "shasum": "" 3913 "shasum": ""
3552 }, 3914 },
3553 "require": { 3915 "require": {
3554 "doctrine/instantiator": "~1.0,>=1.0.2", 3916 "doctrine/instantiator": "^1.0.2",
3555 "php": ">=5.3.3", 3917 "php": ">=5.3.3",
3556 "phpunit/php-text-template": "~1.2", 3918 "phpunit/php-text-template": "~1.2",
3557 "sebastian/exporter": "~1.2" 3919 "sebastian/exporter": "~1.2"
@@ -3590,7 +3952,7 @@
3590 "mock", 3952 "mock",
3591 "xunit" 3953 "xunit"
3592 ], 3954 ],
3593 "time": "2015-07-10 06:54:24" 3955 "time": "2015-08-19 09:14:08"
3594 }, 3956 },
3595 { 3957 {
3596 "name": "sebastian/comparator", 3958 "name": "sebastian/comparator",
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
index 02a6de64..349229f3 100644
--- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
@@ -8,7 +8,6 @@ use Symfony\Component\HttpFoundation\Request;
8use Symfony\Component\HttpFoundation\Response; 8use Symfony\Component\HttpFoundation\Response;
9use Wallabag\CoreBundle\Entity\Entry; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\CoreBundle\Entity\Tag; 10use Wallabag\CoreBundle\Entity\Tag;
11use Wallabag\CoreBundle\Service\Extractor;
12use Hateoas\Configuration\Route; 11use Hateoas\Configuration\Route;
13use Hateoas\Representation\Factory\PagerfantaFactory; 12use Hateoas\Representation\Factory\PagerfantaFactory;
14 13
@@ -147,11 +146,10 @@ class WallabagRestController extends Controller
147 { 146 {
148 $url = $request->request->get('url'); 147 $url = $request->request->get('url');
149 148
150 $content = Extractor::extract($url); 149 $entry = $this->get('wallabag_core.content_proxy')->updateEntry(
151 $entry = new Entry($this->getUser()); 150 new Entry($this->getUser()),
152 $entry->setUrl($url); 151 $url
153 $entry->setTitle($request->request->get('title') ?: $content->getTitle()); 152 );
154 $entry->setContent($content->getBody());
155 153
156 $tags = $request->request->get('tags', ''); 154 $tags = $request->request->get('tags', '');
157 if (!empty($tags)) { 155 if (!empty($tags)) {
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php
index a77489e2..b9e4e67e 100644
--- a/src/Wallabag/CoreBundle/Controller/EntryController.php
+++ b/src/Wallabag/CoreBundle/Controller/EntryController.php
@@ -6,7 +6,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
6use Symfony\Bundle\FrameworkBundle\Controller\Controller; 6use Symfony\Bundle\FrameworkBundle\Controller\Controller;
7use Symfony\Component\HttpFoundation\Request; 7use Symfony\Component\HttpFoundation\Request;
8use Wallabag\CoreBundle\Entity\Entry; 8use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\CoreBundle\Service\Extractor;
10use Wallabag\CoreBundle\Form\Type\NewEntryType; 9use Wallabag\CoreBundle\Form\Type\NewEntryType;
11use Wallabag\CoreBundle\Form\Type\EditEntryType; 10use Wallabag\CoreBundle\Form\Type\EditEntryType;
12use Wallabag\CoreBundle\Filter\EntryFilterType; 11use Wallabag\CoreBundle\Filter\EntryFilterType;
@@ -31,10 +30,7 @@ class EntryController extends Controller
31 $form->handleRequest($request); 30 $form->handleRequest($request);
32 31
33 if ($form->isValid()) { 32 if ($form->isValid()) {
34 $content = Extractor::extract($entry->getUrl()); 33 $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl());
35
36 $entry->setTitle($content->getTitle());
37 $entry->setContent($content->getBody());
38 34
39 $em = $this->getDoctrine()->getManager(); 35 $em = $this->getDoctrine()->getManager();
40 $em->persist($entry); 36 $em->persist($entry);
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index f88d189d..e684c9b1 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -109,6 +109,13 @@ class Entry
109 private $domainName; 109 private $domainName;
110 110
111 /** 111 /**
112 * @var string
113 *
114 * @ORM\Column(name="preview_picture", type="text", nullable=true)
115 */
116 private $previewPicture;
117
118 /**
112 * @var bool 119 * @var bool
113 * 120 *
114 * @ORM\Column(name="is_public", type="boolean", nullable=true, options={"default" = false}) 121 * @ORM\Column(name="is_public", type="boolean", nullable=true, options={"default" = false})
@@ -419,4 +426,28 @@ class Entry
419 { 426 {
420 $this->tags->removeElement($tag); 427 $this->tags->removeElement($tag);
421 } 428 }
429
430 /**
431 * Set previewPicture.
432 *
433 * @param string $previewPicture
434 *
435 * @return Entry
436 */
437 public function setPreviewPicture($previewPicture)
438 {
439 $this->previewPicture = $previewPicture;
440
441 return $this;
442 }
443
444 /**
445 * Get previewPicture.
446 *
447 * @return string
448 */
449 public function getPreviewPicture()
450 {
451 return $this->previewPicture;
452 }
422} 453}
diff --git a/src/Wallabag/CoreBundle/Helper/Content.php b/src/Wallabag/CoreBundle/Helper/Content.php
deleted file mode 100644
index 1cc5e4cf..00000000
--- a/src/Wallabag/CoreBundle/Helper/Content.php
+++ /dev/null
@@ -1,34 +0,0 @@
1<?php
2
3namespace Wallabag\CoreBundle\Helper;
4
5class Content
6{
7 private $title;
8
9 private $body;
10
11 public function __constructor()
12 {
13 }
14
15 public function getTitle()
16 {
17 return $this->title;
18 }
19
20 public function setTitle($title)
21 {
22 $this->title = $title;
23 }
24
25 public function getBody()
26 {
27 return $this->body;
28 }
29
30 public function setBody($body)
31 {
32 $this->body = $body;
33 }
34}
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
new file mode 100644
index 00000000..4565d8e7
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
@@ -0,0 +1,60 @@
1<?php
2
3namespace Wallabag\CoreBundle\Helper;
4
5use Graby\Graby;
6use Wallabag\CoreBundle\Entity\Entry;
7
8/**
9 * This kind of proxy class take care of getting the content from an url
10 * and update the entry with what it found.
11 */
12class ContentProxy
13{
14 protected $graby;
15
16 public function __construct(Graby $graby)
17 {
18 $this->graby = $graby;
19 }
20
21 /**
22 * Fetch content using graby and hydrate given entry with results information.
23 * In case we couldn't find content, we'll try to use Open Graph data.
24 *
25 * @param Entry $entry Entry to update
26 * @param string $url Url to grab content for
27 *
28 * @return Entry
29 */
30 public function updateEntry(Entry $entry, $url)
31 {
32 $content = $this->graby->fetchContent($url);
33
34 $title = $content['title'];
35 if (!$title && isset($content['open_graph']['og_title'])) {
36 $title = $content['open_graph']['og_title'];
37 }
38
39 $html = $content['html'];
40 if (false === $html) {
41 $html = '<p>Unable to retrieve readable content.</p>';
42
43 if (isset($content['open_graph']['og_description'])) {
44 $html .= '<p><i>But we found a short description: </i></p>';
45 $html .= $content['open_graph']['og_description'];
46 }
47 }
48
49 $entry->setUrl($content['url'] ?: $url);
50 $entry->setTitle($title);
51 $entry->setContent($html);
52 $entry->setMimetype($content['content_type']);
53
54 if (isset($content['open_graph']['og_image'])) {
55 $entry->setPreviewPicture($content['open_graph']['og_image']);
56 }
57
58 return $entry;
59 }
60}
diff --git a/src/Wallabag/CoreBundle/Helper/Url.php b/src/Wallabag/CoreBundle/Helper/Url.php
deleted file mode 100644
index 35eb260d..00000000
--- a/src/Wallabag/CoreBundle/Helper/Url.php
+++ /dev/null
@@ -1,28 +0,0 @@
1<?php
2
3namespace Wallabag\CoreBundle\Helper;
4
5class Url
6{
7 public $url;
8
9 public function __construct($url)
10 {
11 $this->url = base64_decode($url);
12 }
13
14 public function getUrl()
15 {
16 return $this->url;
17 }
18
19 public function setUrl($url)
20 {
21 $this->url = $url;
22 }
23
24 public function isCorrect()
25 {
26 return filter_var($this->url, FILTER_VALIDATE_URL) !== false;
27 }
28}
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index 08eae327..3beb5d0e 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -30,3 +30,13 @@ services:
30 wallabag_core.doctrine.prefixed_naming_strategy: 30 wallabag_core.doctrine.prefixed_naming_strategy:
31 class: Wallabag\CoreBundle\Doctrine\Mapping\PrefixedNamingStrategy 31 class: Wallabag\CoreBundle\Doctrine\Mapping\PrefixedNamingStrategy
32 arguments: [%database_table_prefix%] 32 arguments: [%database_table_prefix%]
33
34 wallabag_core.graby:
35 class: Graby\Graby
36 arguments:
37 - { error_message: false }
38
39 wallabag_core.content_proxy:
40 class: Wallabag\CoreBundle\Helper\ContentProxy
41 arguments:
42 - @wallabag_core.graby
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
index 47ca661a..75ac2a6b 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entry.html.twig
@@ -10,7 +10,7 @@
10 <div class="nav-wrapper cyan darken-1"> 10 <div class="nav-wrapper cyan darken-1">
11 <ul> 11 <ul>
12 <li> 12 <li>
13 <a class="waves-effect" href="/"> 13 <a class="waves-effect" href="{{ path('homepage') }}">
14 <i class="mdi-action-exit-to-app"></i> 14 <i class="mdi-action-exit-to-app"></i>
15 </a> 15 </a>
16 </li> 16 </li>
@@ -36,7 +36,7 @@
36 </nav> 36 </nav>
37 <ul id="slide-out" class="collapsible side-nav fixed reader-mode" data-collapsible="accordion"> 37 <ul id="slide-out" class="collapsible side-nav fixed reader-mode" data-collapsible="accordion">
38 <li class="bold border-bottom hide-on-med-and-down"> 38 <li class="bold border-bottom hide-on-med-and-down">
39 <a class="waves-effect collapsible-header" href="/"> 39 <a class="waves-effect collapsible-header" href="{{ path('homepage') }}">
40 <i class="mdi-action-exit-to-app small"></i> 40 <i class="mdi-action-exit-to-app small"></i>
41 <span>{% trans %}back{% endtrans %}</span> 41 <span>{% trans %}back{% endtrans %}</span>
42 </a> 42 </a>
diff --git a/src/Wallabag/CoreBundle/Service/Extractor.php b/src/Wallabag/CoreBundle/Service/Extractor.php
deleted file mode 100644
index 4c067d3a..00000000
--- a/src/Wallabag/CoreBundle/Service/Extractor.php
+++ /dev/null
@@ -1,96 +0,0 @@
1<?php
2
3namespace Wallabag\CoreBundle\Service;
4
5use Wallabag\CoreBundle\Helper\Content;
6use Wallabag\CoreBundle\Helper\Url;
7
8final class Extractor
9{
10 public static function extract($url)
11 {
12 $pageContent = self::getPageContent(new Url(base64_encode($url)));
13 $title = $pageContent['rss']['channel']['item']['title'] ?: parse_url($url, PHP_URL_HOST);
14 $body = $pageContent['rss']['channel']['item']['description'];
15
16 $content = new Content();
17 $content->setTitle($title);
18 $content->setBody($body);
19
20 return $content;
21 }
22
23 /**
24 * Get the content for a given URL (by a call to FullTextFeed).
25 *
26 * @param Url $url
27 *
28 * @return mixed
29 */
30 public static function getPageContent(Url $url)
31 {
32 // Saving and clearing context
33 $REAL = array();
34 foreach ($GLOBALS as $key => $value) {
35 if ($key != 'GLOBALS' && $key != '_SESSION' && $key != 'HTTP_SESSION_VARS') {
36 $GLOBALS[$key] = array();
37 $REAL[$key] = $value;
38 }
39 }
40 // Saving and clearing session
41 if (isset($_SESSION)) {
42 $REAL_SESSION = array();
43 foreach ($_SESSION as $key => $value) {
44 $REAL_SESSION[$key] = $value;
45 unset($_SESSION[$key]);
46 }
47 }
48
49 // Running code in different context
50 $scope = function () {
51 extract(func_get_arg(1));
52 $_GET = $_REQUEST = array(
53 'url' => $url->getUrl(),
54 'max' => 5,
55 'links' => 'preserve',
56 'exc' => '',
57 'format' => 'json',
58 'submit' => 'Create Feed',
59 );
60 ob_start();
61 require func_get_arg(0);
62 $json = ob_get_contents();
63 ob_end_clean();
64
65 return $json;
66 };
67
68 // Silence $scope function to avoid
69 // issues with FTRSS when error_reporting is to high
70 // FTRSS generates PHP warnings which break output
71 $json = @$scope(__DIR__.'/../../../../vendor/wallabag/Fivefilters_Libraries/makefulltextfeed.php', array('url' => $url));
72
73 // Clearing and restoring context
74 foreach ($GLOBALS as $key => $value) {
75 if ($key != 'GLOBALS' && $key != '_SESSION') {
76 unset($GLOBALS[$key]);
77 }
78 }
79 foreach ($REAL as $key => $value) {
80 $GLOBALS[$key] = $value;
81 }
82
83 // Clearing and restoring session
84 if (isset($REAL_SESSION)) {
85 foreach ($_SESSION as $key => $value) {
86 unset($_SESSION[$key]);
87 }
88
89 foreach ($REAL_SESSION as $key => $value) {
90 $_SESSION[$key] = $value;
91 }
92 }
93
94 return json_decode($json, true);
95 }
96}
diff --git a/src/Wallabag/CoreBundle/Tests/Helper/ContentProxyTest.php b/src/Wallabag/CoreBundle/Tests/Helper/ContentProxyTest.php
new file mode 100644
index 00000000..71a004ff
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Tests/Helper/ContentProxyTest.php
@@ -0,0 +1,84 @@
1<?php
2
3namespace Wallabag\CoreBundle\Tests\Helper;
4
5use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
6use Wallabag\CoreBundle\Entity\Entry;
7use Wallabag\CoreBundle\Entity\User;
8use Wallabag\CoreBundle\Helper\ContentProxy;
9
10class ContentProxyTest extends KernelTestCase
11{
12 public function testWithEmptyContent()
13 {
14 $graby = $this->getMockBuilder('Graby\Graby')
15 ->setMethods(array('fetchContent'))
16 ->disableOriginalConstructor()
17 ->getMock();
18
19 $graby->expects($this->any())
20 ->method('fetchContent')
21 ->willReturn(array('html' => false, 'title' => '', 'url' => '', 'content_type' => ''));
22
23 $proxy = new ContentProxy($graby);
24 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
25
26 $this->assertEquals('http://0.0.0.0', $entry->getUrl());
27 $this->assertEmpty($entry->getTitle());
28 $this->assertEquals('<p>Unable to retrieve readable content.</p>', $entry->getContent());
29 $this->assertEmpty($entry->getPreviewPicture());
30 $this->assertEmpty($entry->getMimetype());
31 }
32
33 public function testWithEmptyContentButOG()
34 {
35 $graby = $this->getMockBuilder('Graby\Graby')
36 ->setMethods(array('fetchContent'))
37 ->disableOriginalConstructor()
38 ->getMock();
39
40 $graby->expects($this->any())
41 ->method('fetchContent')
42 ->willReturn(array('html' => false, 'title' => '', 'url' => '', 'content_type' => '', 'open_graph' => array('og_title' => 'my title', 'og_description' => 'desc')));
43
44 $proxy = new ContentProxy($graby);
45 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
46
47 $this->assertEquals('http://0.0.0.0', $entry->getUrl());
48 $this->assertEquals('my title', $entry->getTitle());
49 $this->assertEquals('<p>Unable to retrieve readable content.</p><p><i>But we found a short description: </i></p>desc', $entry->getContent());
50 $this->assertEmpty($entry->getPreviewPicture());
51 $this->assertEmpty($entry->getMimetype());
52 }
53
54 public function testWithContent()
55 {
56 $graby = $this->getMockBuilder('Graby\Graby')
57 ->setMethods(array('fetchContent'))
58 ->disableOriginalConstructor()
59 ->getMock();
60
61 $graby->expects($this->any())
62 ->method('fetchContent')
63 ->willReturn(array(
64 'html' => 'this is my content',
65 'title' => 'this is my title',
66 'url' => 'http://1.1.1.1',
67 'content_type' => 'text/html',
68 'open_graph' => array(
69 'og_title' => 'my OG title',
70 'og_description' => 'OG desc',
71 'og_image' => 'http://3.3.3.3/cover.jpg',
72 ),
73 ));
74
75 $proxy = new ContentProxy($graby);
76 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
77
78 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
79 $this->assertEquals('this is my title', $entry->getTitle());
80 $this->assertEquals('this is my content', $entry->getContent());
81 $this->assertEquals('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture());
82 $this->assertEquals('text/html', $entry->getMimetype());
83 }
84}