diff options
8 files changed, 202 insertions, 126 deletions
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index 97bb3d12..3f4eb17d 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php | |||
@@ -13,6 +13,8 @@ use Wallabag\CoreBundle\Form\Type\EntryFilterType; | |||
13 | use Wallabag\CoreBundle\Form\Type\EditEntryType; | 13 | use Wallabag\CoreBundle\Form\Type\EditEntryType; |
14 | use Wallabag\CoreBundle\Form\Type\NewEntryType; | 14 | use Wallabag\CoreBundle\Form\Type\NewEntryType; |
15 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; | 15 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; |
16 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
17 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | ||
16 | 18 | ||
17 | class EntryController extends Controller | 19 | class EntryController extends Controller |
18 | { | 20 | { |
@@ -81,6 +83,9 @@ class EntryController extends Controller | |||
81 | $em->persist($entry); | 83 | $em->persist($entry); |
82 | $em->flush(); | 84 | $em->flush(); |
83 | 85 | ||
86 | // entry saved, dispatch event about it! | ||
87 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
88 | |||
84 | return $this->redirect($this->generateUrl('homepage')); | 89 | return $this->redirect($this->generateUrl('homepage')); |
85 | } | 90 | } |
86 | 91 | ||
@@ -107,6 +112,9 @@ class EntryController extends Controller | |||
107 | $em = $this->getDoctrine()->getManager(); | 112 | $em = $this->getDoctrine()->getManager(); |
108 | $em->persist($entry); | 113 | $em->persist($entry); |
109 | $em->flush(); | 114 | $em->flush(); |
115 | |||
116 | // entry saved, dispatch event about it! | ||
117 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
110 | } | 118 | } |
111 | 119 | ||
112 | return $this->redirect($this->generateUrl('homepage')); | 120 | return $this->redirect($this->generateUrl('homepage')); |
@@ -343,6 +351,9 @@ class EntryController extends Controller | |||
343 | $em->persist($entry); | 351 | $em->persist($entry); |
344 | $em->flush(); | 352 | $em->flush(); |
345 | 353 | ||
354 | // entry saved, dispatch event about it! | ||
355 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
356 | |||
346 | return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); | 357 | return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); |
347 | } | 358 | } |
348 | 359 | ||
@@ -431,6 +442,9 @@ class EntryController extends Controller | |||
431 | UrlGeneratorInterface::ABSOLUTE_PATH | 442 | UrlGeneratorInterface::ABSOLUTE_PATH |
432 | ); | 443 | ); |
433 | 444 | ||
445 | // entry deleted, dispatch event about it! | ||
446 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | ||
447 | |||
434 | $em = $this->getDoctrine()->getManager(); | 448 | $em = $this->getDoctrine()->getManager(); |
435 | $em->remove($entry); | 449 | $em->remove($entry); |
436 | $em->flush(); | 450 | $em->flush(); |
diff --git a/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php b/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php new file mode 100644 index 00000000..e9061d04 --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php | |||
@@ -0,0 +1,26 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Event; | ||
4 | |||
5 | use Symfony\Component\EventDispatcher\Event; | ||
6 | use Wallabag\CoreBundle\Entity\Entry; | ||
7 | |||
8 | /** | ||
9 | * This event is fired as soon as an entry is deleted. | ||
10 | */ | ||
11 | class EntryDeletedEvent extends Event | ||
12 | { | ||
13 | const NAME = 'entry.deleted'; | ||
14 | |||
15 | protected $entry; | ||
16 | |||
17 | public function __construct(Entry $entry) | ||
18 | { | ||
19 | $this->entry = $entry; | ||
20 | } | ||
21 | |||
22 | public function getEntry() | ||
23 | { | ||
24 | return $this->entry; | ||
25 | } | ||
26 | } | ||
diff --git a/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php b/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php new file mode 100644 index 00000000..5fdb5221 --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php | |||
@@ -0,0 +1,26 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Event; | ||
4 | |||
5 | use Symfony\Component\EventDispatcher\Event; | ||
6 | use Wallabag\CoreBundle\Entity\Entry; | ||
7 | |||
8 | /** | ||
9 | * This event is fired as soon as an entry was saved. | ||
10 | */ | ||
11 | class EntrySavedEvent extends Event | ||
12 | { | ||
13 | const NAME = 'entry.saved'; | ||
14 | |||
15 | protected $entry; | ||
16 | |||
17 | public function __construct(Entry $entry) | ||
18 | { | ||
19 | $this->entry = $entry; | ||
20 | } | ||
21 | |||
22 | public function getEntry() | ||
23 | { | ||
24 | return $this->entry; | ||
25 | } | ||
26 | } | ||
diff --git a/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php index 6fddcea9..4ebe837b 100644 --- a/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php +++ b/src/Wallabag/CoreBundle/Event/Subscriber/DownloadImagesSubscriber.php | |||
@@ -2,110 +2,85 @@ | |||
2 | 2 | ||
3 | namespace Wallabag\CoreBundle\Event\Subscriber; | 3 | namespace Wallabag\CoreBundle\Event\Subscriber; |
4 | 4 | ||
5 | use Doctrine\Common\EventSubscriber; | 5 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
6 | use Doctrine\ORM\Event\LifecycleEventArgs; | ||
7 | use Psr\Log\LoggerInterface; | 6 | use Psr\Log\LoggerInterface; |
8 | use Wallabag\CoreBundle\Helper\DownloadImages; | 7 | use Wallabag\CoreBundle\Helper\DownloadImages; |
9 | use Wallabag\CoreBundle\Entity\Entry; | 8 | use Wallabag\CoreBundle\Entity\Entry; |
9 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
10 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | ||
10 | use Doctrine\ORM\EntityManager; | 11 | use Doctrine\ORM\EntityManager; |
11 | use Craue\ConfigBundle\Util\Config; | ||
12 | 12 | ||
13 | class DownloadImagesSubscriber implements EventSubscriber | 13 | class DownloadImagesSubscriber implements EventSubscriberInterface |
14 | { | 14 | { |
15 | private $configClass; | 15 | private $em; |
16 | private $downloadImages; | 16 | private $downloadImages; |
17 | private $enabled; | ||
17 | private $logger; | 18 | private $logger; |
18 | 19 | ||
19 | /** | 20 | public function __construct(EntityManager $em, DownloadImages $downloadImages, $enabled, LoggerInterface $logger) |
20 | * We inject the class instead of the service otherwise it generates a circular reference with the EntityManager. | ||
21 | * So we build the service ourself when we got the EntityManager (in downloadImages). | ||
22 | */ | ||
23 | public function __construct(DownloadImages $downloadImages, $configClass, LoggerInterface $logger) | ||
24 | { | 21 | { |
22 | $this->em = $em; | ||
25 | $this->downloadImages = $downloadImages; | 23 | $this->downloadImages = $downloadImages; |
26 | $this->configClass = $configClass; | 24 | $this->enabled = $enabled; |
27 | $this->logger = $logger; | 25 | $this->logger = $logger; |
28 | } | 26 | } |
29 | 27 | ||
30 | public function getSubscribedEvents() | 28 | public static function getSubscribedEvents() |
31 | { | 29 | { |
32 | return array( | 30 | return [ |
33 | 'prePersist', | 31 | EntrySavedEvent::NAME => 'onEntrySaved', |
34 | 'preUpdate', | 32 | EntryDeletedEvent::NAME => 'onEntryDeleted', |
35 | ); | 33 | ]; |
36 | } | 34 | } |
37 | 35 | ||
38 | /** | 36 | /** |
39 | * In case of an entry has been updated. | 37 | * Download images and updated the data into the entry. |
40 | * We won't update the content field if it wasn't updated. | ||
41 | * | 38 | * |
42 | * @param LifecycleEventArgs $args | 39 | * @param EntrySavedEvent $event |
43 | */ | 40 | */ |
44 | public function preUpdate(LifecycleEventArgs $args) | 41 | public function onEntrySaved(EntrySavedEvent $event) |
45 | { | 42 | { |
46 | $entity = $args->getEntity(); | 43 | if (!$this->enabled) { |
44 | $this->logger->debug('DownloadImagesSubscriber: disabled.'); | ||
47 | 45 | ||
48 | if (!$entity instanceof Entry) { | ||
49 | return; | 46 | return; |
50 | } | 47 | } |
51 | 48 | ||
52 | $config = new $this->configClass(); | 49 | $entry = $event->getEntry(); |
53 | $config->setEntityManager($args->getEntityManager()); | ||
54 | |||
55 | if (!$config->get('download_images_enabled')) { | ||
56 | return; | ||
57 | } | ||
58 | 50 | ||
59 | // field content has been updated | 51 | $html = $this->downloadImages($entry); |
60 | if ($args->hasChangedField('content')) { | 52 | if (false !== $html) { |
61 | $html = $this->downloadImages($config, $entity); | 53 | $this->logger->debug('DownloadImagesSubscriber: updated html.'); |
62 | 54 | ||
63 | if (false !== $html) { | 55 | $entry->setContent($html); |
64 | $args->setNewValue('content', $html); | ||
65 | } | ||
66 | } | 56 | } |
67 | 57 | ||
68 | // field preview picture has been updated | 58 | // update preview picture |
69 | if ($args->hasChangedField('previewPicture')) { | 59 | $previewPicture = $this->downloadPreviewImage($entry); |
70 | $previewPicture = $this->downloadPreviewImage($config, $entity); | 60 | if (false !== $previewPicture) { |
61 | $this->logger->debug('DownloadImagesSubscriber: update preview picture.'); | ||
71 | 62 | ||
72 | if (false !== $previewPicture) { | 63 | $entry->setPreviewPicture($previewPicture); |
73 | $entity->setPreviewPicture($previewPicture); | ||
74 | } | ||
75 | } | 64 | } |
65 | |||
66 | $this->em->persist($entry); | ||
67 | $this->em->flush(); | ||
76 | } | 68 | } |
77 | 69 | ||
78 | /** | 70 | /** |
79 | * When a new entry is saved. | 71 | * Remove images related to the entry. |
80 | * | 72 | * |
81 | * @param LifecycleEventArgs $args | 73 | * @param EntryDeletedEvent $event |
82 | */ | 74 | */ |
83 | public function prePersist(LifecycleEventArgs $args) | 75 | public function onEntryDeleted(EntryDeletedEvent $event) |
84 | { | 76 | { |
85 | $entity = $args->getEntity(); | 77 | if (!$this->enabled) { |
86 | 78 | $this->logger->debug('DownloadImagesSubscriber: disabled.'); | |
87 | if (!$entity instanceof Entry) { | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | $config = new $this->configClass(); | ||
92 | $config->setEntityManager($args->getEntityManager()); | ||
93 | 79 | ||
94 | if (!$config->get('download_images_enabled')) { | ||
95 | return; | 80 | return; |
96 | } | 81 | } |
97 | 82 | ||
98 | // update all images inside the html | 83 | $this->downloadImages->removeImages($event->getEntry()->getId()); |
99 | $html = $this->downloadImages($config, $entity); | ||
100 | if (false !== $html) { | ||
101 | $entity->setContent($html); | ||
102 | } | ||
103 | |||
104 | // update preview picture | ||
105 | $previewPicture = $this->downloadPreviewImage($config, $entity); | ||
106 | if (false !== $previewPicture) { | ||
107 | $entity->setPreviewPicture($previewPicture); | ||
108 | } | ||
109 | } | 84 | } |
110 | 85 | ||
111 | /** | 86 | /** |
@@ -113,16 +88,14 @@ class DownloadImagesSubscriber implements EventSubscriber | |||
113 | * | 88 | * |
114 | * @todo If we want to add async download, it should be done in that method | 89 | * @todo If we want to add async download, it should be done in that method |
115 | * | 90 | * |
116 | * @param Config $config | 91 | * @param Entry $entry |
117 | * @param Entry $entry | ||
118 | * | 92 | * |
119 | * @return string|false False in case of async | 93 | * @return string|false False in case of async |
120 | */ | 94 | */ |
121 | public function downloadImages(Config $config, Entry $entry) | 95 | private function downloadImages(Entry $entry) |
122 | { | 96 | { |
123 | $this->downloadImages->setWallabagUrl($config->get('wallabag_url')); | ||
124 | |||
125 | return $this->downloadImages->processHtml( | 97 | return $this->downloadImages->processHtml( |
98 | $entry->getId(), | ||
126 | $entry->getContent(), | 99 | $entry->getContent(), |
127 | $entry->getUrl() | 100 | $entry->getUrl() |
128 | ); | 101 | ); |
@@ -133,16 +106,14 @@ class DownloadImagesSubscriber implements EventSubscriber | |||
133 | * | 106 | * |
134 | * @todo If we want to add async download, it should be done in that method | 107 | * @todo If we want to add async download, it should be done in that method |
135 | * | 108 | * |
136 | * @param Config $config | 109 | * @param Entry $entry |
137 | * @param Entry $entry | ||
138 | * | 110 | * |
139 | * @return string|false False in case of async | 111 | * @return string|false False in case of async |
140 | */ | 112 | */ |
141 | public function downloadPreviewImage(Config $config, Entry $entry) | 113 | private function downloadPreviewImage(Entry $entry) |
142 | { | 114 | { |
143 | $this->downloadImages->setWallabagUrl($config->get('wallabag_url')); | ||
144 | |||
145 | return $this->downloadImages->processSingleImage( | 115 | return $this->downloadImages->processSingleImage( |
116 | $entry->getId(), | ||
146 | $entry->getPreviewPicture(), | 117 | $entry->getPreviewPicture(), |
147 | $entry->getUrl() | 118 | $entry->getUrl() |
148 | ); | 119 | ); |
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php index e7982c56..c5298236 100644 --- a/src/Wallabag/CoreBundle/Helper/DownloadImages.php +++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php | |||
@@ -6,6 +6,7 @@ use Psr\Log\LoggerInterface; | |||
6 | use Symfony\Component\DomCrawler\Crawler; | 6 | use Symfony\Component\DomCrawler\Crawler; |
7 | use GuzzleHttp\Client; | 7 | use GuzzleHttp\Client; |
8 | use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser; | 8 | use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser; |
9 | use Symfony\Component\Finder\Finder; | ||
9 | 10 | ||
10 | class DownloadImages | 11 | class DownloadImages |
11 | { | 12 | { |
@@ -17,10 +18,11 @@ class DownloadImages | |||
17 | private $mimeGuesser; | 18 | private $mimeGuesser; |
18 | private $wallabagUrl; | 19 | private $wallabagUrl; |
19 | 20 | ||
20 | public function __construct(Client $client, $baseFolder, LoggerInterface $logger) | 21 | public function __construct(Client $client, $baseFolder, $wallabagUrl, LoggerInterface $logger) |
21 | { | 22 | { |
22 | $this->client = $client; | 23 | $this->client = $client; |
23 | $this->baseFolder = $baseFolder; | 24 | $this->baseFolder = $baseFolder; |
25 | $this->wallabagUrl = rtrim($wallabagUrl, '/'); | ||
24 | $this->logger = $logger; | 26 | $this->logger = $logger; |
25 | $this->mimeGuesser = new MimeTypeExtensionGuesser(); | 27 | $this->mimeGuesser = new MimeTypeExtensionGuesser(); |
26 | 28 | ||
@@ -28,17 +30,6 @@ class DownloadImages | |||
28 | } | 30 | } |
29 | 31 | ||
30 | /** | 32 | /** |
31 | * Since we can't inject CraueConfig service because it'll generate a circular reference when injected in the subscriber | ||
32 | * we use a different way to inject the current wallabag url. | ||
33 | * | ||
34 | * @param string $url Usually from `$config->get('wallabag_url')` | ||
35 | */ | ||
36 | public function setWallabagUrl($url) | ||
37 | { | ||
38 | $this->wallabagUrl = rtrim($url, '/'); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * Setup base folder where all images are going to be saved. | 33 | * Setup base folder where all images are going to be saved. |
43 | */ | 34 | */ |
44 | private function setFolder() | 35 | private function setFolder() |
@@ -52,23 +43,24 @@ class DownloadImages | |||
52 | /** | 43 | /** |
53 | * Process the html and extract image from it, save them to local and return the updated html. | 44 | * Process the html and extract image from it, save them to local and return the updated html. |
54 | * | 45 | * |
46 | * @param int $entryId ID of the entry | ||
55 | * @param string $html | 47 | * @param string $html |
56 | * @param string $url Used as a base path for relative image and folder | 48 | * @param string $url Used as a base path for relative image and folder |
57 | * | 49 | * |
58 | * @return string | 50 | * @return string |
59 | */ | 51 | */ |
60 | public function processHtml($html, $url) | 52 | public function processHtml($entryId, $html, $url) |
61 | { | 53 | { |
62 | $crawler = new Crawler($html); | 54 | $crawler = new Crawler($html); |
63 | $result = $crawler | 55 | $result = $crawler |
64 | ->filterXpath('//img') | 56 | ->filterXpath('//img') |
65 | ->extract(array('src')); | 57 | ->extract(array('src')); |
66 | 58 | ||
67 | $relativePath = $this->getRelativePath($url); | 59 | $relativePath = $this->getRelativePath($entryId); |
68 | 60 | ||
69 | // download and save the image to the folder | 61 | // download and save the image to the folder |
70 | foreach ($result as $image) { | 62 | foreach ($result as $image) { |
71 | $imagePath = $this->processSingleImage($image, $url, $relativePath); | 63 | $imagePath = $this->processSingleImage($entryId, $image, $url, $relativePath); |
72 | 64 | ||
73 | if (false === $imagePath) { | 65 | if (false === $imagePath) { |
74 | continue; | 66 | continue; |
@@ -86,24 +78,27 @@ class DownloadImages | |||
86 | * - re-saved it (for security reason) | 78 | * - re-saved it (for security reason) |
87 | * - return the new local path. | 79 | * - return the new local path. |
88 | * | 80 | * |
81 | * @param int $entryId ID of the entry | ||
89 | * @param string $imagePath Path to the image to retrieve | 82 | * @param string $imagePath Path to the image to retrieve |
90 | * @param string $url Url from where the image were found | 83 | * @param string $url Url from where the image were found |
91 | * @param string $relativePath Relative local path to saved the image | 84 | * @param string $relativePath Relative local path to saved the image |
92 | * | 85 | * |
93 | * @return string Relative url to access the image from the web | 86 | * @return string Relative url to access the image from the web |
94 | */ | 87 | */ |
95 | public function processSingleImage($imagePath, $url, $relativePath = null) | 88 | public function processSingleImage($entryId, $imagePath, $url, $relativePath = null) |
96 | { | 89 | { |
97 | if (null == $relativePath) { | 90 | if (null === $relativePath) { |
98 | $relativePath = $this->getRelativePath($url); | 91 | $relativePath = $this->getRelativePath($entryId); |
99 | } | 92 | } |
100 | 93 | ||
94 | $this->logger->debug('DownloadImages: working on image: '.$imagePath); | ||
95 | |||
101 | $folderPath = $this->baseFolder.'/'.$relativePath; | 96 | $folderPath = $this->baseFolder.'/'.$relativePath; |
102 | 97 | ||
103 | // build image path | 98 | // build image path |
104 | $absolutePath = $this->getAbsoluteLink($url, $imagePath); | 99 | $absolutePath = $this->getAbsoluteLink($url, $imagePath); |
105 | if (false === $absolutePath) { | 100 | if (false === $absolutePath) { |
106 | $this->logger->log('error', 'Can not determine the absolute path for that image, skipping.'); | 101 | $this->logger->error('DownloadImages: Can not determine the absolute path for that image, skipping.'); |
107 | 102 | ||
108 | return false; | 103 | return false; |
109 | } | 104 | } |
@@ -111,15 +106,15 @@ class DownloadImages | |||
111 | try { | 106 | try { |
112 | $res = $this->client->get($absolutePath); | 107 | $res = $this->client->get($absolutePath); |
113 | } catch (\Exception $e) { | 108 | } catch (\Exception $e) { |
114 | $this->logger->log('error', 'Can not retrieve image, skipping.', ['exception' => $e]); | 109 | $this->logger->error('DownloadImages: Can not retrieve image, skipping.', ['exception' => $e]); |
115 | 110 | ||
116 | return false; | 111 | return false; |
117 | } | 112 | } |
118 | 113 | ||
119 | $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); | 114 | $ext = $this->mimeGuesser->guess($res->getHeader('content-type')); |
120 | $this->logger->log('debug', 'Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); | 115 | $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]); |
121 | if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) { | 116 | if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) { |
122 | $this->logger->log('error', 'Processed image with not allowed extension. Skipping '.$imagePath); | 117 | $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping '.$imagePath); |
123 | 118 | ||
124 | return false; | 119 | return false; |
125 | } | 120 | } |
@@ -133,7 +128,7 @@ class DownloadImages | |||
133 | } | 128 | } |
134 | 129 | ||
135 | if (false === $im) { | 130 | if (false === $im) { |
136 | $this->logger->log('error', 'Error while regenerating image', ['path' => $localPath]); | 131 | $this->logger->error('DownloadImages: Error while regenerating image', ['path' => $localPath]); |
137 | 132 | ||
138 | return false; | 133 | return false; |
139 | } | 134 | } |
@@ -141,16 +136,16 @@ class DownloadImages | |||
141 | switch ($ext) { | 136 | switch ($ext) { |
142 | case 'gif': | 137 | case 'gif': |
143 | $result = imagegif($im, $localPath); | 138 | $result = imagegif($im, $localPath); |
144 | $this->logger->log('debug', 'Re-creating gif'); | 139 | $this->logger->debug('DownloadImages: Re-creating gif'); |
145 | break; | 140 | break; |
146 | case 'jpeg': | 141 | case 'jpeg': |
147 | case 'jpg': | 142 | case 'jpg': |
148 | $result = imagejpeg($im, $localPath, self::REGENERATE_PICTURES_QUALITY); | 143 | $result = imagejpeg($im, $localPath, self::REGENERATE_PICTURES_QUALITY); |
149 | $this->logger->log('debug', 'Re-creating jpg'); | 144 | $this->logger->debug('DownloadImages: Re-creating jpg'); |
150 | break; | 145 | break; |
151 | case 'png': | 146 | case 'png': |
152 | $result = imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9)); | 147 | $result = imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9)); |
153 | $this->logger->log('debug', 'Re-creating png'); | 148 | $this->logger->debug('DownloadImages: Re-creating png'); |
154 | } | 149 | } |
155 | 150 | ||
156 | imagedestroy($im); | 151 | imagedestroy($im); |
@@ -159,23 +154,46 @@ class DownloadImages | |||
159 | } | 154 | } |
160 | 155 | ||
161 | /** | 156 | /** |
157 | * Remove all images for the given entry id. | ||
158 | * | ||
159 | * @param int $entryId ID of the entry | ||
160 | */ | ||
161 | public function removeImages($entryId) | ||
162 | { | ||
163 | $relativePath = $this->getRelativePath($entryId); | ||
164 | $folderPath = $this->baseFolder.'/'.$relativePath; | ||
165 | |||
166 | $finder = new Finder(); | ||
167 | $finder | ||
168 | ->files() | ||
169 | ->ignoreDotFiles(true) | ||
170 | ->in($folderPath); | ||
171 | |||
172 | foreach ($finder as $file) { | ||
173 | @unlink($file->getRealPath()); | ||
174 | } | ||
175 | |||
176 | @rmdir($folderPath); | ||
177 | } | ||
178 | |||
179 | /** | ||
162 | * Generate the folder where we are going to save images based on the entry url. | 180 | * Generate the folder where we are going to save images based on the entry url. |
163 | * | 181 | * |
164 | * @param string $url | 182 | * @param int $entryId ID of the entry |
165 | * | 183 | * |
166 | * @return string | 184 | * @return string |
167 | */ | 185 | */ |
168 | private function getRelativePath($url) | 186 | private function getRelativePath($entryId) |
169 | { | 187 | { |
170 | $hashUrl = hash('crc32', $url); | 188 | $hashId = hash('crc32', $entryId); |
171 | $relativePath = $hashUrl[0].'/'.$hashUrl[1].'/'.$hashUrl; | 189 | $relativePath = $hashId[0].'/'.$hashId[1].'/'.$hashId; |
172 | $folderPath = $this->baseFolder.'/'.$relativePath; | 190 | $folderPath = $this->baseFolder.'/'.$relativePath; |
173 | 191 | ||
174 | if (!file_exists($folderPath)) { | 192 | if (!file_exists($folderPath)) { |
175 | mkdir($folderPath, 0777, true); | 193 | mkdir($folderPath, 0777, true); |
176 | } | 194 | } |
177 | 195 | ||
178 | $this->logger->log('debug', 'Folder used for that url', ['folder' => $folderPath, 'url' => $url]); | 196 | $this->logger->debug('DownloadImages: Folder used for that Entry id', ['folder' => $folderPath, 'entryId' => $entryId]); |
179 | 197 | ||
180 | return $relativePath; | 198 | return $relativePath; |
181 | } | 199 | } |
@@ -208,7 +226,7 @@ class DownloadImages | |||
208 | return $absolute->get_uri(); | 226 | return $absolute->get_uri(); |
209 | } | 227 | } |
210 | 228 | ||
211 | $this->logger->log('error', 'Can not make an absolute link', ['base' => $base, 'url' => $url]); | 229 | $this->logger->error('DownloadImages: Can not make an absolute link', ['base' => $base, 'url' => $url]); |
212 | 230 | ||
213 | return false; | 231 | return false; |
214 | } | 232 | } |
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index 1fb81a46..56d776ad 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml | |||
@@ -140,17 +140,19 @@ services: | |||
140 | wallabag_core.subscriber.download_images: | 140 | wallabag_core.subscriber.download_images: |
141 | class: Wallabag\CoreBundle\Event\Subscriber\DownloadImagesSubscriber | 141 | class: Wallabag\CoreBundle\Event\Subscriber\DownloadImagesSubscriber |
142 | arguments: | 142 | arguments: |
143 | - "@doctrine.orm.default_entity_manager" | ||
143 | - "@wallabag_core.entry.download_images" | 144 | - "@wallabag_core.entry.download_images" |
144 | - "%craue_config.config.class%" | 145 | - '@=service(''craue_config'').get(''download_images_enabled'')' |
145 | - "@logger" | 146 | - "@logger" |
146 | tags: | 147 | tags: |
147 | - { name: doctrine.event_subscriber } | 148 | - { name: kernel.event_subscriber } |
148 | 149 | ||
149 | wallabag_core.entry.download_images: | 150 | wallabag_core.entry.download_images: |
150 | class: Wallabag\CoreBundle\Helper\DownloadImages | 151 | class: Wallabag\CoreBundle\Helper\DownloadImages |
151 | arguments: | 152 | arguments: |
152 | - "@wallabag_core.entry.download_images.client" | 153 | - "@wallabag_core.entry.download_images.client" |
153 | - "%kernel.root_dir%/../web/assets/images" | 154 | - "%kernel.root_dir%/../web/assets/images" |
155 | - '@=service(''craue_config'').get(''wallabag_url'')' | ||
154 | - "@logger" | 156 | - "@logger" |
155 | 157 | ||
156 | wallabag_core.entry.download_images.client: | 158 | wallabag_core.entry.download_images.client: |
diff --git a/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php b/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php index 514e9d89..4ab06dbf 100644 --- a/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php +++ b/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php | |||
@@ -869,10 +869,30 @@ class EntryControllerTest extends WallabagCoreTestCase | |||
869 | $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $entry); | 869 | $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $entry); |
870 | $this->assertEquals($url, $entry->getUrl()); | 870 | $this->assertEquals($url, $entry->getUrl()); |
871 | $this->assertContains('Perpignan', $entry->getTitle()); | 871 | $this->assertContains('Perpignan', $entry->getTitle()); |
872 | $this->assertContains('assets/images/8/e/8ec9229a/d9bc0fcd.jpeg', $entry->getContent()); | 872 | $this->assertContains('/d9bc0fcd.jpeg', $entry->getContent()); |
873 | 873 | ||
874 | $em->remove($entry); | 874 | $client->getContainer()->get('craue_config')->set('download_images_enabled', 0); |
875 | $em->flush(); | 875 | } |
876 | |||
877 | /** | ||
878 | * @depends testNewEntryWithDownloadImagesEnabled | ||
879 | */ | ||
880 | public function testRemoveEntryWithDownloadImagesEnabled() | ||
881 | { | ||
882 | $this->logInAs('admin'); | ||
883 | $client = $this->getClient(); | ||
884 | |||
885 | $url = 'http://www.20minutes.fr/montpellier/1952003-20161030-video-car-tombe-panne-rugbymen-perpignan-improvisent-melee-route'; | ||
886 | $client->getContainer()->get('craue_config')->set('download_images_enabled', 1); | ||
887 | |||
888 | $content = $client->getContainer() | ||
889 | ->get('doctrine.orm.entity_manager') | ||
890 | ->getRepository('WallabagCoreBundle:Entry') | ||
891 | ->findByUrlAndUserId($url, $this->getLoggedInUserId()); | ||
892 | |||
893 | $client->request('GET', '/delete/'.$content->getId()); | ||
894 | |||
895 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
876 | 896 | ||
877 | $client->getContainer()->get('craue_config')->set('download_images_enabled', 0); | 897 | $client->getContainer()->get('craue_config')->set('download_images_enabled', 0); |
878 | } | 898 | } |
diff --git a/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php b/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php index 33d2e389..920c21d9 100644 --- a/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php +++ b/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php | |||
@@ -26,12 +26,11 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase | |||
26 | $logHandler = new TestHandler(); | 26 | $logHandler = new TestHandler(); |
27 | $logger = new Logger('test', array($logHandler)); | 27 | $logger = new Logger('test', array($logHandler)); |
28 | 28 | ||
29 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', $logger); | 29 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); |
30 | $download->setWallabagUrl('http://wallabag.io/'); | ||
31 | 30 | ||
32 | $res = $download->processHtml('<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY'); | 31 | $res = $download->processHtml(123, '<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY'); |
33 | 32 | ||
34 | $this->assertContains('http://wallabag.io/assets/images/4/2/4258f71e/c638b4c2.png', $res); | 33 | $this->assertContains('http://wallabag.io/assets/images/9/b/9b0ead26/c638b4c2.png', $res); |
35 | } | 34 | } |
36 | 35 | ||
37 | public function testProcessHtmlWithBadImage() | 36 | public function testProcessHtmlWithBadImage() |
@@ -47,8 +46,8 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase | |||
47 | $logHandler = new TestHandler(); | 46 | $logHandler = new TestHandler(); |
48 | $logger = new Logger('test', array($logHandler)); | 47 | $logger = new Logger('test', array($logHandler)); |
49 | 48 | ||
50 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', $logger); | 49 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); |
51 | $res = $download->processHtml('<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY'); | 50 | $res = $download->processHtml(123, '<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY'); |
52 | 51 | ||
53 | $this->assertContains('http://i.imgur.com/T9qgcHc.jpg', $res, 'Image were not replace because of content-type'); | 52 | $this->assertContains('http://i.imgur.com/T9qgcHc.jpg', $res, 'Image were not replace because of content-type'); |
54 | } | 53 | } |
@@ -79,10 +78,10 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase | |||
79 | $logHandler = new TestHandler(); | 78 | $logHandler = new TestHandler(); |
80 | $logger = new Logger('test', array($logHandler)); | 79 | $logger = new Logger('test', array($logHandler)); |
81 | 80 | ||
82 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', $logger); | 81 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); |
83 | $res = $download->processSingleImage('T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); | 82 | $res = $download->processSingleImage(123, 'T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); |
84 | 83 | ||
85 | $this->assertContains('/assets/images/4/2/4258f71e/ebe60399.'.$extension, $res); | 84 | $this->assertContains('/assets/images/9/b/9b0ead26/ebe60399.'.$extension, $res); |
86 | } | 85 | } |
87 | 86 | ||
88 | public function testProcessSingleImageWithBadUrl() | 87 | public function testProcessSingleImageWithBadUrl() |
@@ -98,8 +97,8 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase | |||
98 | $logHandler = new TestHandler(); | 97 | $logHandler = new TestHandler(); |
99 | $logger = new Logger('test', array($logHandler)); | 98 | $logger = new Logger('test', array($logHandler)); |
100 | 99 | ||
101 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', $logger); | 100 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); |
102 | $res = $download->processSingleImage('T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); | 101 | $res = $download->processSingleImage(123, 'T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); |
103 | 102 | ||
104 | $this->assertFalse($res, 'Image can not be found, so it will not be replaced'); | 103 | $this->assertFalse($res, 'Image can not be found, so it will not be replaced'); |
105 | } | 104 | } |
@@ -117,8 +116,8 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase | |||
117 | $logHandler = new TestHandler(); | 116 | $logHandler = new TestHandler(); |
118 | $logger = new Logger('test', array($logHandler)); | 117 | $logger = new Logger('test', array($logHandler)); |
119 | 118 | ||
120 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', $logger); | 119 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); |
121 | $res = $download->processSingleImage('http://i.imgur.com/T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); | 120 | $res = $download->processSingleImage(123, 'http://i.imgur.com/T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); |
122 | 121 | ||
123 | $this->assertFalse($res, 'Image can not be loaded, so it will not be replaced'); | 122 | $this->assertFalse($res, 'Image can not be loaded, so it will not be replaced'); |
124 | } | 123 | } |
@@ -136,8 +135,8 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase | |||
136 | $logHandler = new TestHandler(); | 135 | $logHandler = new TestHandler(); |
137 | $logger = new Logger('test', array($logHandler)); | 136 | $logger = new Logger('test', array($logHandler)); |
138 | 137 | ||
139 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', $logger); | 138 | $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); |
140 | $res = $download->processSingleImage('/i.imgur.com/T9qgcHc.jpg', 'imgur.com/gallery/WxtWY'); | 139 | $res = $download->processSingleImage(123, '/i.imgur.com/T9qgcHc.jpg', 'imgur.com/gallery/WxtWY'); |
141 | 140 | ||
142 | $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced'); | 141 | $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced'); |
143 | } | 142 | } |