diff options
8 files changed, 715 insertions, 14 deletions
diff --git a/composer.json b/composer.json index a46e990a..a25e143a 100644 --- a/composer.json +++ b/composer.json | |||
@@ -55,7 +55,9 @@ | |||
55 | "j0k3r/graby": "~1.0", | 55 | "j0k3r/graby": "~1.0", |
56 | "friendsofsymfony/user-bundle": "dev-master", | 56 | "friendsofsymfony/user-bundle": "dev-master", |
57 | "friendsofsymfony/oauth-server-bundle": "^1.4@dev", | 57 | "friendsofsymfony/oauth-server-bundle": "^1.4@dev", |
58 | "scheb/two-factor-bundle": "~1.4" | 58 | "scheb/two-factor-bundle": "~1.4", |
59 | "grandt/phpepub": "~4.0", | ||
60 | "wallabag/phpMobi": "~1.0.0" | ||
59 | }, | 61 | }, |
60 | "require-dev": { | 62 | "require-dev": { |
61 | "doctrine/doctrine-fixtures-bundle": "~2.2.0", | 63 | "doctrine/doctrine-fixtures-bundle": "~2.2.0", |
@@ -63,6 +65,12 @@ | |||
63 | "phpunit/phpunit": "~4.4", | 65 | "phpunit/phpunit": "~4.4", |
64 | "symfony/phpunit-bridge": "~2.7.0" | 66 | "symfony/phpunit-bridge": "~2.7.0" |
65 | }, | 67 | }, |
68 | "repositories": [ | ||
69 | { | ||
70 | "type": "vcs", | ||
71 | "url": "https://github.com/wallabag/phpMobi" | ||
72 | } | ||
73 | ], | ||
66 | "scripts": { | 74 | "scripts": { |
67 | "post-install-cmd": [ | 75 | "post-install-cmd": [ |
68 | "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", | 76 | "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", |
diff --git a/composer.lock b/composer.lock index ec11324f..c634abbd 100644 --- a/composer.lock +++ b/composer.lock | |||
@@ -1089,6 +1089,244 @@ | |||
1089 | "time": "2015-11-03 10:24:23" | 1089 | "time": "2015-11-03 10:24:23" |
1090 | }, | 1090 | }, |
1091 | { | 1091 | { |
1092 | "name": "grandt/binstring", | ||
1093 | "version": "1.0.0", | ||
1094 | "source": { | ||
1095 | "type": "git", | ||
1096 | "url": "https://github.com/Grandt/PHPBinString.git", | ||
1097 | "reference": "825fe2ac8a68190f651fc2dbc07b6edde18bc431" | ||
1098 | }, | ||
1099 | "dist": { | ||
1100 | "type": "zip", | ||
1101 | "url": "https://api.github.com/repos/Grandt/PHPBinString/zipball/825fe2ac8a68190f651fc2dbc07b6edde18bc431", | ||
1102 | "reference": "825fe2ac8a68190f651fc2dbc07b6edde18bc431", | ||
1103 | "shasum": "" | ||
1104 | }, | ||
1105 | "require": { | ||
1106 | "php": ">=5.0" | ||
1107 | }, | ||
1108 | "type": "library", | ||
1109 | "autoload": { | ||
1110 | "classmap": [ | ||
1111 | "BinString.php", | ||
1112 | "BinStringStatic.php" | ||
1113 | ] | ||
1114 | }, | ||
1115 | "notification-url": "https://packagist.org/downloads/", | ||
1116 | "license": [ | ||
1117 | "LGPL-2.1" | ||
1118 | ], | ||
1119 | "authors": [ | ||
1120 | { | ||
1121 | "name": "A. Grandt", | ||
1122 | "email": "php@grandt.com", | ||
1123 | "role": "Developer" | ||
1124 | } | ||
1125 | ], | ||
1126 | "description": "A class for working around the use of mbstring.func_override", | ||
1127 | "homepage": "https://github.com/Grandt/PHPBinString", | ||
1128 | "keywords": [ | ||
1129 | "binary strings", | ||
1130 | "mbstring" | ||
1131 | ], | ||
1132 | "time": "2015-08-13 06:14:41" | ||
1133 | }, | ||
1134 | { | ||
1135 | "name": "grandt/phpepub", | ||
1136 | "version": "4.0.3", | ||
1137 | "source": { | ||
1138 | "type": "git", | ||
1139 | "url": "https://github.com/Grandt/PHPePub.git", | ||
1140 | "reference": "dee0c5549a8d2c6bf6a1ad5b4ee21d245b711fca" | ||
1141 | }, | ||
1142 | "dist": { | ||
1143 | "type": "zip", | ||
1144 | "url": "https://api.github.com/repos/Grandt/PHPePub/zipball/dee0c5549a8d2c6bf6a1ad5b4ee21d245b711fca", | ||
1145 | "reference": "dee0c5549a8d2c6bf6a1ad5b4ee21d245b711fca", | ||
1146 | "shasum": "" | ||
1147 | }, | ||
1148 | "require": { | ||
1149 | "grandt/phpresizegif": ">=1.0.3", | ||
1150 | "grandt/relativepath": ">=1.0.1", | ||
1151 | "php": ">=5.3.0", | ||
1152 | "phpzip/phpzip": ">=2.0.7" | ||
1153 | }, | ||
1154 | "type": "library", | ||
1155 | "autoload": { | ||
1156 | "psr-4": { | ||
1157 | "PHPePub\\": "src/PHPePub" | ||
1158 | }, | ||
1159 | "classmap": [ | ||
1160 | "src/lib.uuid.php" | ||
1161 | ] | ||
1162 | }, | ||
1163 | "notification-url": "https://packagist.org/downloads/", | ||
1164 | "license": [ | ||
1165 | "LGPL-2.1" | ||
1166 | ], | ||
1167 | "authors": [ | ||
1168 | { | ||
1169 | "name": "A. Grandt", | ||
1170 | "email": "php@grandt.com", | ||
1171 | "homepage": "http://grandt.com", | ||
1172 | "role": "Developer" | ||
1173 | } | ||
1174 | ], | ||
1175 | "description": "Package to create and stream e-books in the ePub 2.0 and 3.0 formats.", | ||
1176 | "homepage": "https://github.com/Grandt/PHPZip", | ||
1177 | "keywords": [ | ||
1178 | "e-book", | ||
1179 | "epub" | ||
1180 | ], | ||
1181 | "time": "2015-09-15 08:47:09" | ||
1182 | }, | ||
1183 | { | ||
1184 | "name": "grandt/phpresizegif", | ||
1185 | "version": "1.0.3", | ||
1186 | "source": { | ||
1187 | "type": "git", | ||
1188 | "url": "https://github.com/Grandt/PHPResizeGif.git", | ||
1189 | "reference": "775f6810fcda2fd1d8ca881d44a80c8d310ae7fe" | ||
1190 | }, | ||
1191 | "dist": { | ||
1192 | "type": "zip", | ||
1193 | "url": "https://api.github.com/repos/Grandt/PHPResizeGif/zipball/775f6810fcda2fd1d8ca881d44a80c8d310ae7fe", | ||
1194 | "reference": "775f6810fcda2fd1d8ca881d44a80c8d310ae7fe", | ||
1195 | "shasum": "" | ||
1196 | }, | ||
1197 | "require": { | ||
1198 | "grandt/binstring": ">=0.2.0", | ||
1199 | "php": ">=5.3.0" | ||
1200 | }, | ||
1201 | "type": "library", | ||
1202 | "autoload": { | ||
1203 | "psr-4": { | ||
1204 | "grandt\\ResizeGif\\": "src/ResizeGif", | ||
1205 | "grandt\\ResizeGif\\Files\\": "src/ResizeGif/Files", | ||
1206 | "grandt\\ResizeGif\\Structure\\": "src/ResizeGif/Structure", | ||
1207 | "grandt\\ResizeGif\\Debug\\": "src/ResizeGif/Debug" | ||
1208 | } | ||
1209 | }, | ||
1210 | "notification-url": "https://packagist.org/downloads/", | ||
1211 | "license": [ | ||
1212 | "LGPL-2.1" | ||
1213 | ], | ||
1214 | "authors": [ | ||
1215 | { | ||
1216 | "name": "A. Grandt", | ||
1217 | "email": "php@grandt.com", | ||
1218 | "homepage": "http://grandt.com", | ||
1219 | "role": "Developer" | ||
1220 | } | ||
1221 | ], | ||
1222 | "description": "GIF89a compliant Gif resizer, including transparency and optimized gifs with sub sized elements.", | ||
1223 | "homepage": "https://github.com/Grandt/PHPResizeGif", | ||
1224 | "keywords": [ | ||
1225 | "GIF89a", | ||
1226 | "animated gif", | ||
1227 | "gif", | ||
1228 | "resize" | ||
1229 | ], | ||
1230 | "time": "2015-05-10 10:52:24" | ||
1231 | }, | ||
1232 | { | ||
1233 | "name": "grandt/phpzipmerge", | ||
1234 | "version": "1.0.4", | ||
1235 | "source": { | ||
1236 | "type": "git", | ||
1237 | "url": "https://github.com/Grandt/PHPZipMerge.git", | ||
1238 | "reference": "0b1273d3c2dbfe244904158b1dbd65a663264fb9" | ||
1239 | }, | ||
1240 | "dist": { | ||
1241 | "type": "zip", | ||
1242 | "url": "https://api.github.com/repos/Grandt/PHPZipMerge/zipball/0b1273d3c2dbfe244904158b1dbd65a663264fb9", | ||
1243 | "reference": "0b1273d3c2dbfe244904158b1dbd65a663264fb9", | ||
1244 | "shasum": "" | ||
1245 | }, | ||
1246 | "require": { | ||
1247 | "grandt/binstring": ">=1.0.0", | ||
1248 | "grandt/relativepath": ">=1.0.1", | ||
1249 | "php": ">=5.3.0" | ||
1250 | }, | ||
1251 | "type": "library", | ||
1252 | "autoload": { | ||
1253 | "psr-4": { | ||
1254 | "ZipMerge\\": "src/ZipMerge" | ||
1255 | } | ||
1256 | }, | ||
1257 | "notification-url": "https://packagist.org/downloads/", | ||
1258 | "license": [ | ||
1259 | "LGPL-2.1" | ||
1260 | ], | ||
1261 | "authors": [ | ||
1262 | { | ||
1263 | "name": "A. Grandt", | ||
1264 | "email": "php@grandt.com", | ||
1265 | "homepage": "http://grandt.com", | ||
1266 | "role": "Developer" | ||
1267 | }, | ||
1268 | { | ||
1269 | "name": "Greg Kappatos", | ||
1270 | "homepage": "http://websiteconnect.com.au", | ||
1271 | "role": "Developer" | ||
1272 | } | ||
1273 | ], | ||
1274 | "description": "Merge and stream multiple Zip files on the fly.", | ||
1275 | "homepage": "https://github.com/Grandt/PHPZipMerge", | ||
1276 | "keywords": [ | ||
1277 | "archive", | ||
1278 | "compressed", | ||
1279 | "compression", | ||
1280 | "merge", | ||
1281 | "phpzip", | ||
1282 | "pkzip", | ||
1283 | "stream", | ||
1284 | "zip" | ||
1285 | ], | ||
1286 | "time": "2015-08-18 13:49:33" | ||
1287 | }, | ||
1288 | { | ||
1289 | "name": "grandt/relativepath", | ||
1290 | "version": "1.0.2", | ||
1291 | "source": { | ||
1292 | "type": "git", | ||
1293 | "url": "https://github.com/Grandt/PHPRelativePath.git", | ||
1294 | "reference": "19541133c24143b6295688472c54dd6ed15a5462" | ||
1295 | }, | ||
1296 | "dist": { | ||
1297 | "type": "zip", | ||
1298 | "url": "https://api.github.com/repos/Grandt/PHPRelativePath/zipball/19541133c24143b6295688472c54dd6ed15a5462", | ||
1299 | "reference": "19541133c24143b6295688472c54dd6ed15a5462", | ||
1300 | "shasum": "" | ||
1301 | }, | ||
1302 | "require": { | ||
1303 | "php": ">=5.0" | ||
1304 | }, | ||
1305 | "type": "library", | ||
1306 | "autoload": { | ||
1307 | "classmap": [ | ||
1308 | "RelativePath.php" | ||
1309 | ] | ||
1310 | }, | ||
1311 | "notification-url": "https://packagist.org/downloads/", | ||
1312 | "license": [ | ||
1313 | "LGPL-2.1" | ||
1314 | ], | ||
1315 | "authors": [ | ||
1316 | { | ||
1317 | "name": "A. Grandt", | ||
1318 | "email": "php@grandt.com", | ||
1319 | "role": "Developer" | ||
1320 | } | ||
1321 | ], | ||
1322 | "description": "A class for cleaning up/collapsing relative paths. Like real_path, but without the need for the path to exist on the filesystem.", | ||
1323 | "homepage": "https://github.com/Grandt/PHPRelativePath", | ||
1324 | "keywords": [ | ||
1325 | "file path" | ||
1326 | ], | ||
1327 | "time": "2015-05-14 08:18:23" | ||
1328 | }, | ||
1329 | { | ||
1092 | "name": "guzzlehttp/guzzle", | 1330 | "name": "guzzlehttp/guzzle", |
1093 | "version": "5.3.0", | 1331 | "version": "5.3.0", |
1094 | "source": { | 1332 | "source": { |
@@ -1394,20 +1632,20 @@ | |||
1394 | } | 1632 | } |
1395 | ], | 1633 | ], |
1396 | "description": "Graby helps you extract article content from web pages", | 1634 | "description": "Graby helps you extract article content from web pages", |
1397 | "time": "2015-10-28 06:38:06" | 1635 | "time": "2015-10-14 17:55:10" |
1398 | }, | 1636 | }, |
1399 | { | 1637 | { |
1400 | "name": "j0k3r/graby-site-config", | 1638 | "name": "j0k3r/graby-site-config", |
1401 | "version": "1.0.6", | 1639 | "version": "1.0.5", |
1402 | "source": { | 1640 | "source": { |
1403 | "type": "git", | 1641 | "type": "git", |
1404 | "url": "https://github.com/j0k3r/graby-site-config.git", | 1642 | "url": "https://github.com/j0k3r/graby-site-config.git", |
1405 | "reference": "6631451c1be563ff3bc8fa16c60ef7df38f8e65b" | 1643 | "reference": "44afb3d6a90a816752426537e92e85160bdb40b9" |
1406 | }, | 1644 | }, |
1407 | "dist": { | 1645 | "dist": { |
1408 | "type": "zip", | 1646 | "type": "zip", |
1409 | "url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/6631451c1be563ff3bc8fa16c60ef7df38f8e65b", | 1647 | "url": "https://api.github.com/repos/j0k3r/graby-site-config/zipball/44afb3d6a90a816752426537e92e85160bdb40b9", |
1410 | "reference": "6631451c1be563ff3bc8fa16c60ef7df38f8e65b", | 1648 | "reference": "44afb3d6a90a816752426537e92e85160bdb40b9", |
1411 | "shasum": "" | 1649 | "shasum": "" |
1412 | }, | 1650 | }, |
1413 | "require": { | 1651 | "require": { |
@@ -1900,16 +2138,16 @@ | |||
1900 | }, | 2138 | }, |
1901 | { | 2139 | { |
1902 | "name": "lexik/form-filter-bundle", | 2140 | "name": "lexik/form-filter-bundle", |
1903 | "version": "v4.0.2", | 2141 | "version": "v4.0.1", |
1904 | "source": { | 2142 | "source": { |
1905 | "type": "git", | 2143 | "type": "git", |
1906 | "url": "https://github.com/lexik/LexikFormFilterBundle.git", | 2144 | "url": "https://github.com/lexik/LexikFormFilterBundle.git", |
1907 | "reference": "d6081d308b71e14509602722c78d28801e4ed78a" | 2145 | "reference": "8e54a41376eab7890d4deea4088ad5c86df964ee" |
1908 | }, | 2146 | }, |
1909 | "dist": { | 2147 | "dist": { |
1910 | "type": "zip", | 2148 | "type": "zip", |
1911 | "url": "https://api.github.com/repos/lexik/LexikFormFilterBundle/zipball/d6081d308b71e14509602722c78d28801e4ed78a", | 2149 | "url": "https://api.github.com/repos/lexik/LexikFormFilterBundle/zipball/8e54a41376eab7890d4deea4088ad5c86df964ee", |
1912 | "reference": "d6081d308b71e14509602722c78d28801e4ed78a", | 2150 | "reference": "8e54a41376eab7890d4deea4088ad5c86df964ee", |
1913 | "shasum": "" | 2151 | "shasum": "" |
1914 | }, | 2152 | }, |
1915 | "require": { | 2153 | "require": { |
@@ -2524,6 +2762,67 @@ | |||
2524 | "time": "2015-07-25 16:39:46" | 2762 | "time": "2015-07-25 16:39:46" |
2525 | }, | 2763 | }, |
2526 | { | 2764 | { |
2765 | "name": "phpzip/phpzip", | ||
2766 | "version": "2.0.7", | ||
2767 | "source": { | ||
2768 | "type": "git", | ||
2769 | "url": "https://github.com/Grandt/PHPZip.git", | ||
2770 | "reference": "a43a7ce8b2f21050f8b143876c5c1661b0d65306" | ||
2771 | }, | ||
2772 | "dist": { | ||
2773 | "type": "zip", | ||
2774 | "url": "https://api.github.com/repos/Grandt/PHPZip/zipball/a43a7ce8b2f21050f8b143876c5c1661b0d65306", | ||
2775 | "reference": "a43a7ce8b2f21050f8b143876c5c1661b0d65306", | ||
2776 | "shasum": "" | ||
2777 | }, | ||
2778 | "require": { | ||
2779 | "grandt/binstring": ">=0.2.0", | ||
2780 | "grandt/phpzipmerge": ">=1.0.3", | ||
2781 | "grandt/relativepath": ">=1.0.1", | ||
2782 | "php": ">=5.3.0" | ||
2783 | }, | ||
2784 | "type": "library", | ||
2785 | "autoload": { | ||
2786 | "psr-4": { | ||
2787 | "PHPZip\\Zip\\": "src/Zip" | ||
2788 | } | ||
2789 | }, | ||
2790 | "notification-url": "https://packagist.org/downloads/", | ||
2791 | "license": [ | ||
2792 | "LGPL-2.1" | ||
2793 | ], | ||
2794 | "authors": [ | ||
2795 | { | ||
2796 | "name": "Adam Schmalhofer", | ||
2797 | "email": "Adam.Schmalhofer@gmx.de", | ||
2798 | "role": "Developer" | ||
2799 | }, | ||
2800 | { | ||
2801 | "name": "A. Grandt", | ||
2802 | "email": "php@grandt.com", | ||
2803 | "homepage": "http://grandt.com", | ||
2804 | "role": "Developer" | ||
2805 | }, | ||
2806 | { | ||
2807 | "name": "Greg Kappatos", | ||
2808 | "homepage": "http://websiteconnect.com.au", | ||
2809 | "role": "Developer" | ||
2810 | } | ||
2811 | ], | ||
2812 | "description": "Package to create and stream archives of compressed files in ZIP format with PHP 5.3+", | ||
2813 | "homepage": "https://github.com/Grandt/PHPZip", | ||
2814 | "keywords": [ | ||
2815 | "archive", | ||
2816 | "compressed", | ||
2817 | "compression", | ||
2818 | "phpzip", | ||
2819 | "pkzip", | ||
2820 | "stream", | ||
2821 | "zip" | ||
2822 | ], | ||
2823 | "time": "2015-04-30 06:45:53" | ||
2824 | }, | ||
2825 | { | ||
2527 | "name": "psr/log", | 2826 | "name": "psr/log", |
2528 | "version": "1.0.0", | 2827 | "version": "1.0.0", |
2529 | "source": { | 2828 | "source": { |
@@ -3497,6 +3796,43 @@ | |||
3497 | "time": "2015-11-05 12:49:06" | 3796 | "time": "2015-11-05 12:49:06" |
3498 | }, | 3797 | }, |
3499 | { | 3798 | { |
3799 | "name": "wallabag/phpMobi", | ||
3800 | "version": "1.0.0", | ||
3801 | "source": { | ||
3802 | "type": "git", | ||
3803 | "url": "https://github.com/wallabag/phpMobi.git", | ||
3804 | "reference": "5137696542f08f8e6a0603c01970c6d3eca9873d" | ||
3805 | }, | ||
3806 | "dist": { | ||
3807 | "type": "zip", | ||
3808 | "url": "https://api.github.com/repos/wallabag/phpMobi/zipball/5137696542f08f8e6a0603c01970c6d3eca9873d", | ||
3809 | "reference": "5137696542f08f8e6a0603c01970c6d3eca9873d", | ||
3810 | "shasum": "" | ||
3811 | }, | ||
3812 | "require": { | ||
3813 | "php": ">=5.3.0" | ||
3814 | }, | ||
3815 | "type": "library", | ||
3816 | "autoload": { | ||
3817 | "files": [ | ||
3818 | "MOBIClass/MOBI.php" | ||
3819 | ] | ||
3820 | }, | ||
3821 | "authors": [ | ||
3822 | { | ||
3823 | "name": "Nicolas LÅ“uillet", | ||
3824 | "email": "nicolas@loeuillet.org", | ||
3825 | "homepage": "http://www.cdetc.fr" | ||
3826 | } | ||
3827 | ], | ||
3828 | "description": "An experimental Mobipocket file creator in PHP.", | ||
3829 | "homepage": "https://github.com/wallabag/phpMobi", | ||
3830 | "support": { | ||
3831 | "source": "https://github.com/wallabag/phpMobi/tree/1.0.0" | ||
3832 | }, | ||
3833 | "time": "2015-01-19 12:43:17" | ||
3834 | }, | ||
3835 | { | ||
3500 | "name": "willdurand/hateoas", | 3836 | "name": "willdurand/hateoas", |
3501 | "version": "v2.6.0", | 3837 | "version": "v2.6.0", |
3502 | "source": { | 3838 | "source": { |
diff --git a/src/Wallabag/CoreBundle/Controller/ExportController.php b/src/Wallabag/CoreBundle/Controller/ExportController.php new file mode 100644 index 00000000..123e491a --- /dev/null +++ b/src/Wallabag/CoreBundle/Controller/ExportController.php | |||
@@ -0,0 +1,65 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
7 | use Wallabag\CoreBundle\Entity\Entry; | ||
8 | use Wallabag\CoreBundle\Helper\EntriesExport; | ||
9 | |||
10 | class ExportController extends Controller | ||
11 | { | ||
12 | /** | ||
13 | * Gets all entries for current user. | ||
14 | * | ||
15 | * @Route("/export/{category}.{format}", name="ebook", requirements={ | ||
16 | * "_format": "epub|mobi|pdf|json|xml|txt|csv" | ||
17 | * }) | ||
18 | */ | ||
19 | public function getEntriesAction($format, $category) | ||
20 | { | ||
21 | $repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry'); | ||
22 | switch ($category) { | ||
23 | case 'all': | ||
24 | $method = 'All'; | ||
25 | break; | ||
26 | |||
27 | case 'unread': | ||
28 | $method = 'Unread'; | ||
29 | break; | ||
30 | |||
31 | case 'starred': | ||
32 | $method = 'Starred'; | ||
33 | break; | ||
34 | |||
35 | case 'archive': | ||
36 | $method = 'Archive'; | ||
37 | break; | ||
38 | |||
39 | default: | ||
40 | break; | ||
41 | } | ||
42 | |||
43 | $methodBuilder = 'getBuilderFor'.$method.'ByUser'; | ||
44 | $qb = $repository->$methodBuilder($this->getUser()->getId()); | ||
45 | $entries = $qb->getQuery()->getResult(); | ||
46 | |||
47 | $export = new EntriesExport($entries); | ||
48 | $export->setMethod($method); | ||
49 | $export->exportAs($format); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Gets one entry content. | ||
54 | * | ||
55 | * @param Entry $entry | ||
56 | * | ||
57 | * @Route("/export/id/{id}.{format}", requirements={"id" = "\d+"}, name="ebook_entry") | ||
58 | */ | ||
59 | public function getEntryAction(Entry $entry, $format) | ||
60 | { | ||
61 | $export = new EntriesExport(array($entry)); | ||
62 | $export->setMethod('entry'); | ||
63 | $export->exportAs($format); | ||
64 | } | ||
65 | } | ||
diff --git a/src/Wallabag/CoreBundle/Helper/EntriesExport.php b/src/Wallabag/CoreBundle/Helper/EntriesExport.php new file mode 100644 index 00000000..fad0bb97 --- /dev/null +++ b/src/Wallabag/CoreBundle/Helper/EntriesExport.php | |||
@@ -0,0 +1,263 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Helper; | ||
4 | |||
5 | use PHPePub\Core\EPub; | ||
6 | use PHPePub\Core\Structure\OPF\DublinCore; | ||
7 | |||
8 | class EntriesExport | ||
9 | { | ||
10 | private $format; | ||
11 | private $method; | ||
12 | private $title; | ||
13 | private $entries; | ||
14 | private $authors = array('wallabag'); | ||
15 | private $language; | ||
16 | private $tags; | ||
17 | |||
18 | public function __construct($entries) | ||
19 | { | ||
20 | $this->entries = $entries; | ||
21 | |||
22 | foreach ($entries as $entry) { | ||
23 | $this->tags[] = $entry->getTags(); | ||
24 | } | ||
25 | if (count($entries) === 1) { | ||
26 | $this->language = $entries[0]->getLanguage(); | ||
27 | } | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * Sets the category of which we want to get articles, or just one entry. | ||
32 | * | ||
33 | * @param string $method Method to get articles | ||
34 | */ | ||
35 | public function setMethod($method) | ||
36 | { | ||
37 | $this->method = $method; | ||
38 | |||
39 | switch ($this->method) { | ||
40 | case 'All': | ||
41 | $this->title = 'All Articles'; | ||
42 | break; | ||
43 | case 'Unread': | ||
44 | $this->title = 'Unread articles'; | ||
45 | break; | ||
46 | case 'Starred': | ||
47 | $this->title = 'Starred articles'; | ||
48 | break; | ||
49 | case 'Archive': | ||
50 | $this->title = 'Archived articles'; | ||
51 | break; | ||
52 | case 'entry': | ||
53 | $this->title = $this->entries[0]->getTitle(); | ||
54 | break; | ||
55 | default: | ||
56 | break; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Sets the output format. | ||
62 | * | ||
63 | * @param string $format | ||
64 | */ | ||
65 | public function exportAs($format) | ||
66 | { | ||
67 | $this->format = $format; | ||
68 | |||
69 | switch ($this->format) { | ||
70 | case 'epub': | ||
71 | $this->produceEpub(); | ||
72 | break; | ||
73 | |||
74 | case 'mobi': | ||
75 | $this->produceMobi(); | ||
76 | break; | ||
77 | |||
78 | case 'pdf': | ||
79 | $this->producePDF(); | ||
80 | break; | ||
81 | |||
82 | case 'csv': | ||
83 | $this->produceCSV(); | ||
84 | break; | ||
85 | |||
86 | default: | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | private function produceEpub() | ||
92 | { | ||
93 | /* | ||
94 | * Start and End of the book | ||
95 | */ | ||
96 | $content_start = | ||
97 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | ||
98 | ."<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n" | ||
99 | .'<head>' | ||
100 | ."<meta http-equiv=\"Default-Style\" content=\"text/html; charset=utf-8\" />\n" | ||
101 | .'<title>'._('wallabag articles book')."</title>\n" | ||
102 | ."</head>\n" | ||
103 | ."<body>\n"; | ||
104 | |||
105 | $bookEnd = "</body>\n</html>\n"; | ||
106 | |||
107 | $book = new EPub(EPub::BOOK_VERSION_EPUB3); | ||
108 | |||
109 | /* | ||
110 | * Book metadata | ||
111 | */ | ||
112 | |||
113 | $book->setTitle($this->title); | ||
114 | $book->setIdentifier($this->title, EPub::IDENTIFIER_URI); // Could also be the ISBN number, prefered for published books, or a UUID. | ||
115 | $book->setLanguage($this->language); // Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc. | ||
116 | $book->setDescription(_('Some articles saved on my wallabag')); | ||
117 | |||
118 | foreach ($this->authors as $author) { | ||
119 | $book->setAuthor($author, $author); | ||
120 | } | ||
121 | |||
122 | $book->setPublisher('wallabag', 'wallabag'); // I hope this is a non existant address :) | ||
123 | $book->setDate(time()); // Strictly not needed as the book date defaults to time(). | ||
124 | $book->setSourceURL("http://$_SERVER[HTTP_HOST]"); | ||
125 | |||
126 | $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'PHP'); | ||
127 | $book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'wallabag'); | ||
128 | |||
129 | /* | ||
130 | * Front page | ||
131 | */ | ||
132 | |||
133 | $book->setCoverImage('Cover.png', file_get_contents('themes/_global/img/appicon/apple-touch-icon-152.png'), 'image/png'); | ||
134 | |||
135 | $cover = $content_start.'<div style="text-align:center;"><p>'._('Produced by wallabag with PHPePub').'</p><p>'._('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.').'</p></div>'.$bookEnd; | ||
136 | |||
137 | $book->addChapter('Notices', 'Cover2.html', $cover); | ||
138 | |||
139 | $book->buildTOC(); | ||
140 | |||
141 | /* | ||
142 | * Adding actual entries | ||
143 | */ | ||
144 | |||
145 | foreach ($this->entries as $entry) { //set tags as subjects | ||
146 | foreach ($this->tags as $tag) { | ||
147 | $book->setSubject($tag['value']); | ||
148 | } | ||
149 | |||
150 | $chapter = $content_start.$entry->getContent().$bookEnd; | ||
151 | $book->addChapter($entry->getTitle(), htmlspecialchars($entry->getTitle()).'.html', $chapter, true, EPub::EXTERNAL_REF_ADD); | ||
152 | } | ||
153 | $book->finalize(); | ||
154 | $book->sendBook($this->title); | ||
155 | } | ||
156 | |||
157 | private function produceMobi() | ||
158 | { | ||
159 | $mobi = new \MOBI(); | ||
160 | $content = new \MOBIFile(); | ||
161 | |||
162 | /* | ||
163 | * Book metadata | ||
164 | */ | ||
165 | |||
166 | $content->set('title', $this->title); | ||
167 | $content->set('author', implode($this->authors)); | ||
168 | $content->set('subject', $this->title); | ||
169 | |||
170 | /* | ||
171 | * Front page | ||
172 | */ | ||
173 | |||
174 | $content->appendParagraph('<div style="text-align:center;" ><p>'._('Produced by wallabag with PHPMobi').'</p><p>'._('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.').'</p></div>'); | ||
175 | $content->appendImage(imagecreatefrompng('themes/_global/img/appicon/apple-touch-icon-152.png')); | ||
176 | $content->appendPageBreak(); | ||
177 | |||
178 | /* | ||
179 | * Adding actual entries | ||
180 | */ | ||
181 | |||
182 | foreach ($this->entries as $entry) { | ||
183 | $content->appendChapterTitle($entry->getTitle()); | ||
184 | $content->appendParagraph($entry->getContent()); | ||
185 | $content->appendPageBreak(); | ||
186 | } | ||
187 | $mobi->setContentProvider($content); | ||
188 | |||
189 | // the browser inside Kindle Devices doesn't likes special caracters either, we limit to A-z/0-9 | ||
190 | $this->title = preg_replace('/[^A-Za-z0-9\-]/', '', $this->title); | ||
191 | |||
192 | // we offer file to download | ||
193 | $mobi->download($this->title.'.mobi'); | ||
194 | } | ||
195 | |||
196 | private function producePDF() | ||
197 | { | ||
198 | $pdf = new \TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); | ||
199 | |||
200 | /* | ||
201 | * Book metadata | ||
202 | */ | ||
203 | |||
204 | $pdf->SetCreator(PDF_CREATOR); | ||
205 | $pdf->SetAuthor('wallabag'); | ||
206 | $pdf->SetTitle($this->title); | ||
207 | $pdf->SetSubject('Articles via wallabag'); | ||
208 | $pdf->SetKeywords('wallabag'); | ||
209 | |||
210 | /* | ||
211 | * Front page | ||
212 | */ | ||
213 | |||
214 | $pdf->AddPage(); | ||
215 | $intro = '<h1>'.$this->title.'</h1><div style="text-align:center;" > | ||
216 | <p>'._('Produced by wallabag with tcpdf').'</p> | ||
217 | <p>'._('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.').'</p> | ||
218 | <img src="themes/_global/img/appicon/apple-touch-icon-152.png" /></div>'; | ||
219 | |||
220 | $pdf->writeHTMLCell(0, 0, '', '', $intro, 0, 1, 0, true, '', true); | ||
221 | |||
222 | /* | ||
223 | * Adding actual entries | ||
224 | */ | ||
225 | |||
226 | foreach ($this->entries as $entry) { | ||
227 | foreach ($this->tags as $tag) { | ||
228 | $pdf->SetKeywords($tag['value']); | ||
229 | } | ||
230 | |||
231 | $pdf->AddPage(); | ||
232 | $html = '<h1>'.$entry->getTitle().'</h1>'; | ||
233 | $html .= $entry->getContent(); | ||
234 | $pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true); | ||
235 | } | ||
236 | |||
237 | // set image scale factor | ||
238 | $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); | ||
239 | |||
240 | $pdf->Output($this->title.'.pdf', 'D'); | ||
241 | } | ||
242 | |||
243 | private function produceCSV() | ||
244 | { | ||
245 | header('Content-type: application/csv'); | ||
246 | header('Content-Disposition: attachment; filename="'.$this->title.'.csv"'); | ||
247 | header('Content-Transfer-Encoding: UTF-8'); | ||
248 | |||
249 | $output = fopen('php://output', 'a'); | ||
250 | |||
251 | fputcsv($output, array('Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language')); | ||
252 | foreach ($this->entries as $entry) { | ||
253 | fputcsv($output, array($entry->getTitle(), | ||
254 | $entry->getURL(), | ||
255 | $entry->getContent(), | ||
256 | implode(', ', $entry->getTags()->toArray()), | ||
257 | $entry->getMimetype(), | ||
258 | $entry->getLanguage(), )); | ||
259 | } | ||
260 | fclose($output); | ||
261 | exit(); | ||
262 | } | ||
263 | } | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig index 668824bc..5a231c86 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Entry/entries.html.twig | |||
@@ -91,6 +91,24 @@ | |||
91 | {% endfor %} | 91 | {% endfor %} |
92 | </ul> | 92 | </ul> |
93 | 93 | ||
94 | <!-- Export --> | ||
95 | <div id="export" class="side-nav fixed right-aligned"> | ||
96 | {% set currentRoute = app.request.attributes.get('_route') %} | ||
97 | {% if currentRoute == 'homepage' %} | ||
98 | {% set currentRoute = 'unread' %} | ||
99 | {% endif %} | ||
100 | <h4 class="center">{% trans %}Export{% endtrans %}</h4> | ||
101 | <ul> | ||
102 | <li class="bold"><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'epub' }) }}">{% trans %}EPUB{% endtrans %}</a></li> | ||
103 | <li class="bold"><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'mobi' }) }}">{% trans %}MOBI{% endtrans %}</a></li> | ||
104 | <li class="bold"><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'pdf' }) }}">{% trans %}PDF{% endtrans %}</a></li> | ||
105 | <li class="bold"><del><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'xml' }) }}">{% trans %}XML{% endtrans %}</a></del></li> | ||
106 | <li class="bold"><del><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'json' }) }}">{% trans %}JSON{% endtrans %}</a></del></li> | ||
107 | <li class="bold"><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'csv' }) }}">{% trans %}CSV{% endtrans %}</a></li> | ||
108 | <li class="bold"><del><a class="waves-effect" href="{{ path('ebook', { 'category': currentRoute, 'format': 'txt' }) }}">{% trans %}TXT{% endtrans %}</a></del></li> | ||
109 | </ul> | ||
110 | </div> | ||
111 | |||
94 | <!-- Filters --> | 112 | <!-- Filters --> |
95 | <div id="filters" class="side-nav fixed right-aligned"> | 113 | <div id="filters" class="side-nav fixed right-aligned"> |
96 | <form action="{{ path('all') }}"> | 114 | <form action="{{ path('all') }}"> |
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 7230506c..bece099a 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 | |||
@@ -102,13 +102,14 @@ | |||
102 | <li class="bold"> | 102 | <li class="bold"> |
103 | <a class="waves-effect collapsible-header"> | 103 | <a class="waves-effect collapsible-header"> |
104 | <i class="mdi-file-file-download small"></i> | 104 | <i class="mdi-file-file-download small"></i> |
105 | <span><del>{% trans %}Download{% endtrans %}</del></span> | 105 | <span>{% trans %}Download{% endtrans %}</span> |
106 | </a> | 106 | </a> |
107 | <div class="collapsible-body"> | 107 | <div class="collapsible-body"> |
108 | <ul> | 108 | <ul> |
109 | {% if export_epub %}<li><del><a href="?epub&method=id&value={{ entry.id }}" title="Generate ePub file">EPUB</a></del></li>{% endif %} | 109 | {% if export_epub %}<li><a href="{{ path('ebook_entry', { 'id': entry.id, 'format': 'epub' }) }}" title="Generate ePub file">EPUB</a></li>{% endif %} |
110 | {% if export_mobi %}<li><del><a href="?mobi&method=id&value={{ entry.id }}" title="Generate Mobi file">MOBI</a></del></li>{% endif %} | 110 | {% if export_mobi %}<li><a href="{{ path('ebook_entry', { 'id': entry.id, 'format': 'mobi' }) }}" title="Generate Mobi file">MOBI</a></li>{% endif %} |
111 | {% if export_pdf %}<li><del><a href="?pdf&method=id&value={{ entry.id }}" title="Generate PDF file">PDF</a></del> </li>{% endif %} | 111 | {% if export_pdf %}<li><a href="{{ path('ebook_entry', { 'id': entry.id, 'format': 'pdf' }) }}" title="Generate PDF file">PDF</a></li>{% endif %} |
112 | <li><a href="{{ path('ebook_entry', { 'id': entry.id, 'format': 'csv' }) }}" title="Generate CSV file">CSV</a></li> | ||
112 | </ul> | 113 | </ul> |
113 | </div> | 114 | </div> |
114 | </li> | 115 | </li> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig index 95b3977c..f426e25b 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig | |||
@@ -59,6 +59,7 @@ | |||
59 | <li class="bold"><a title="{% trans %}Add a new entry{% endtrans %}" class="waves-effect" href="{{ path('new') }}" id="nav-btn-add"><i class="mdi-content-add"></i></a></li> | 59 | <li class="bold"><a title="{% trans %}Add a new entry{% endtrans %}" class="waves-effect" href="{{ path('new') }}" id="nav-btn-add"><i class="mdi-content-add"></i></a></li> |
60 | <li><a title="{% trans %}Search{% endtrans %}" class="waves-effect" href="javascript: void(null);" id="nav-btn-search"><i class="mdi-action-search"></i></a> | 60 | <li><a title="{% trans %}Search{% endtrans %}" class="waves-effect" href="javascript: void(null);" id="nav-btn-search"><i class="mdi-action-search"></i></a> |
61 | <li id="button_filters"><a title="{% trans %}Filter entries{% endtrans %}" href="#" data-activates="filters" class="nav-panel-menu button-collapse-right"><i class="mdi-content-filter-list"></i></a></li> | 61 | <li id="button_filters"><a title="{% trans %}Filter entries{% endtrans %}" href="#" data-activates="filters" class="nav-panel-menu button-collapse-right"><i class="mdi-content-filter-list"></i></a></li> |
62 | <li id="button_export"><a title="{% trans %}Export{% endtrans %}" class="nav-panel-menu button-collapse-right" href="#" data-activates="export" class="nav-panel-menu button-collapse-right"><i class="mdi-file-file-download"></i></a></li> | ||
62 | </ul> | 63 | </ul> |
63 | </div> | 64 | </div> |
64 | <form method="get" action="index.php"> | 65 | <form method="get" action="index.php"> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/public/js/init.js b/src/Wallabag/CoreBundle/Resources/views/themes/material/public/js/init.js index edfdee82..491a7916 100755 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/public/js/init.js +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/public/js/init.js | |||
@@ -11,6 +11,14 @@ function init_filters() { | |||
11 | } | 11 | } |
12 | } | 12 | } |
13 | 13 | ||
14 | function init_export() { | ||
15 | // no display if export not aviable | ||
16 | if ($("div").is("#export")) { | ||
17 | $('#button_export').show(); | ||
18 | $('.button-collapse-right').sideNav({ edge: 'right' }); | ||
19 | } | ||
20 | } | ||
21 | |||
14 | $(document).ready(function(){ | 22 | $(document).ready(function(){ |
15 | // sideNav | 23 | // sideNav |
16 | $('.button-collapse').sideNav(); | 24 | $('.button-collapse').sideNav(); |
@@ -26,6 +34,7 @@ $(document).ready(function(){ | |||
26 | format: 'dd/mm/yyyy', | 34 | format: 'dd/mm/yyyy', |
27 | }); | 35 | }); |
28 | init_filters(); | 36 | init_filters(); |
37 | init_export(); | ||
29 | 38 | ||
30 | $('#nav-btn-add-tag').on('click', function(){ | 39 | $('#nav-btn-add-tag').on('click', function(){ |
31 | $(".nav-panel-add-tag").toggle(100); | 40 | $(".nav-panel-add-tag").toggle(100); |