]>
Commit | Line | Data |
---|---|---|
1 | <?php | |
2 | ||
3 | namespace Wallabag\CoreBundle\Command; | |
4 | ||
5 | use Doctrine\ORM\NoResultException; | |
6 | use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; | |
7 | use Symfony\Component\Console\Input\InputArgument; | |
8 | use Symfony\Component\Console\Input\InputInterface; | |
9 | use Symfony\Component\Console\Output\OutputInterface; | |
10 | use Wallabag\CoreBundle\Entity\Entry; | |
11 | use Wallabag\UserBundle\Entity\User; | |
12 | ||
13 | class CleanDuplicatesCommand extends ContainerAwareCommand | |
14 | { | |
15 | /** @var OutputInterface */ | |
16 | protected $output; | |
17 | ||
18 | protected $duplicates = 0; | |
19 | ||
20 | protected function configure() | |
21 | { | |
22 | $this | |
23 | ->setName('wallabag:clean-duplicates') | |
24 | ->setDescription('Cleans the database for duplicates') | |
25 | ->setHelp('This command helps you to clean your articles list in case of duplicates') | |
26 | ->addArgument( | |
27 | 'username', | |
28 | InputArgument::OPTIONAL, | |
29 | 'User to clean' | |
30 | ); | |
31 | } | |
32 | ||
33 | protected function execute(InputInterface $input, OutputInterface $output) | |
34 | { | |
35 | $this->output = $output; | |
36 | ||
37 | $username = $input->getArgument('username'); | |
38 | ||
39 | if ($username) { | |
40 | try { | |
41 | $user = $this->getUser($username); | |
42 | $this->cleanDuplicates($user); | |
43 | } catch (NoResultException $e) { | |
44 | $output->writeln(sprintf('<error>User "%s" not found.</error>', $username)); | |
45 | ||
46 | return 1; | |
47 | } | |
48 | } else { | |
49 | $users = $this->getContainer()->get('wallabag_user.user_repository')->findAll(); | |
50 | ||
51 | $output->writeln(sprintf('Cleaning through %d user accounts', count($users))); | |
52 | ||
53 | foreach ($users as $user) { | |
54 | $output->writeln(sprintf('Processing user %s', $user->getUsername())); | |
55 | $this->cleanDuplicates($user); | |
56 | } | |
57 | $output->writeln(sprintf('Finished cleaning. %d duplicates found in total', $this->duplicates)); | |
58 | } | |
59 | ||
60 | return 0; | |
61 | } | |
62 | ||
63 | /** | |
64 | * @param User $user | |
65 | */ | |
66 | private function cleanDuplicates(User $user) | |
67 | { | |
68 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); | |
69 | $repo = $this->getContainer()->get('wallabag_core.entry_repository'); | |
70 | ||
71 | $entries = $repo->getAllEntriesIdAndUrl($user->getId()); | |
72 | ||
73 | $duplicatesCount = 0; | |
74 | $urls = []; | |
75 | foreach ($entries as $entry) { | |
76 | $url = $this->similarUrl($entry['url']); | |
77 | ||
78 | /* @var $entry Entry */ | |
79 | if (in_array($url, $urls)) { | |
80 | ++$duplicatesCount; | |
81 | ||
82 | $em->remove($repo->find($entry['id'])); | |
83 | $em->flush(); // Flushing at the end of the loop would require the instance not being online | |
84 | } else { | |
85 | $urls[] = $entry['url']; | |
86 | } | |
87 | } | |
88 | ||
89 | $this->duplicates += $duplicatesCount; | |
90 | ||
91 | $this->output->writeln(sprintf('Cleaned %d duplicates for user %s', $duplicatesCount, $user->getUserName())); | |
92 | } | |
93 | ||
94 | private function similarUrl($url) | |
95 | { | |
96 | if (in_array(substr($url, -1), ['/', '#'])) { // get rid of "/" and "#" and the end of urls | |
97 | return substr($url, 0, strlen($url)); | |
98 | } | |
99 | ||
100 | return $url; | |
101 | } | |
102 | ||
103 | /** | |
104 | * Fetches a user from its username. | |
105 | * | |
106 | * @param string $username | |
107 | * | |
108 | * @return \Wallabag\UserBundle\Entity\User | |
109 | */ | |
110 | private function getUser($username) | |
111 | { | |
112 | return $this->getContainer()->get('wallabag_user.user_repository')->findOneByUserName($username); | |
113 | } | |
114 | ||
115 | private function getDoctrine() | |
116 | { | |
117 | return $this->getContainer()->get('doctrine'); | |
118 | } | |
119 | } |