Completed
Push — master ( 923939...b71e6c )
by
unknown
102:02 queued 47:03
created

PhotoUpdateCommand::execute()   D

Complexity

Conditions 14
Paths 258

Size

Total Lines 80

Duplication

Lines 7
Ratio 8.75 %

Importance

Changes 0
Metric Value
dl 7
loc 80
rs 4.203
c 0
b 0
f 0
cc 14
nc 258
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace KI\UserBundle\Command;
3
use KI\UserBundle\Entity\User;
4
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
5
use Symfony\Component\Console\Input\InputArgument;
6
use Symfony\Component\Console\Input\InputOption;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Output\OutputInterface;
9
use Symfony\Component\Console\Question\ConfirmationQuestion;
10
use Symfony\Component\Serializer\Serializer;
11
use Symfony\Component\Serializer\Encoder\CsvEncoder;
12
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
13
class PhotoUpdateCommand extends ContainerAwareCommand
14
{
15
    protected $FACEBOOK_API_URL = 'https://graph.facebook.com/v2.10';
16
    protected function configure()
17
    {
18
        $this
19
            ->setName('upont:update:photo')
20
            ->setDescription('Import missing photos from Facebook for the given promo')
21
            ->addArgument('promo', InputArgument::REQUIRED, 'The promo whose photos are to be updated.')
22
            ->addArgument('file', InputArgument::REQUIRED, 'Absolute path to a csv containing facebook_name,facebook_id')
23
            ->addOption('preview', 'p', InputOption::VALUE_NONE, 'Make a preview of the photos to be imported without importing them')
24
            ->addOption('all', 'a', InputOption::VALUE_NONE, 'Treat the users regardless whether they already have a photo on uPont')
25
            ->addOption('interactive', 'i', InputOption::VALUE_NONE, 'For each match, ask interactively whether the photo should be updated')
26
            ->addOption('similarity-threshold', 's', InputOption::VALUE_REQUIRED, 'Similarity threshold with Fb profiles above which photos are imported in non-preview and non-interactive mode (in % between 0 and 100)', 85)
27
        ;
28
    }
29
    protected function execute(InputInterface $input, OutputInterface $output)
30
    {
31
        $em = $this->getContainer()->get('doctrine')->getManager();
32
        $usersRepo = $this->getContainer()->get('doctrine')->getRepository(User::class);
33
        $curlService = $this->getContainer()->get('ki_core.service.curl');
34
        $imageService = $this->getContainer()->get('ki_core.service.image');
35
        $questionHelper = $this->getHelper('question');
36
        $isPreview = $input->getOption('preview');
37
        $users = $usersRepo->findByPromo($input->getArgument('promo'));
38
        $question = new ConfirmationQuestion('Update? ', false, '/^y/i');
39
	$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
40
        $csvData = $serializer->decode(file_get_contents($input->getArgument('file')), 'csv');
41
        $noPhotoCount = 0;
42
        $notFoundCount = 0;
43
        $updatedNoPhotoCount = 0;
44
        $updatedExistingPhotoCount = 0;
45
	$similarityThreshold = $input->getOption("similarity-threshold");
46
        $output->writeln('Importing facebook photos for users (> ' . $similarityThreshold . '% similar) :');
47
        foreach ($users as $user) {
48
            $noPhoto = $user->imageUrl() === 'uploads/others/default-user.png';
49
            if (!$noPhoto) {
50
                $noPhotoCount++;
51
            }
52
            if ($noPhoto || $input->getOption('all')) {
53
                // Find best match
54
                $bestMatch = null;
55
                $bestPercent = -1;
56 View Code Duplication
                foreach ($csvData as $member) {
57
                    $percent = $this->isSimilar($user, $member);
58
                    if ($percent > $bestPercent) {
59
                        $bestPercent = $percent;
60
                        $bestMatch = $member;
61
                    }
62
                }
63
                if ($bestPercent > $similarityThreshold) {
64
                    $userFullName = $user->getFirstName() . ' ' . $user->getLastName();
65
                    $pictureInfo = $noPhoto ? '[Picture MISSING]' : '[Picture exists]';
66
                    $output->writeln($userFullName . ' <- ' . $bestMatch['name'] . ' (' . $bestPercent . '% similar) ' . $pictureInfo);
67
                    $updateConfirmation = $input->getOption('interactive') ? $questionHelper->ask($input, $output, $question) : true;
68
                    if ($updateConfirmation) {
69
                        if (!$noPhoto) {
70
                            $updatedExistingPhotoCount++;
71
                        } else {
72
                            $updatedNoPhotoCount++;
73
                        }
74
                        if(!$isPreview) {
75
                            $url = '/' . $bestMatch['id'] . '/picture?width=9999&redirect=false';
76
                            $dataImage = json_decode($curlService->curl($this->FACEBOOK_API_URL . $url), true);
77
                            $image = $imageService->upload($dataImage['data']['url'], true);
78
                            $user->setImage($image);
79
                        }
80
                    }
81
                }
82
                else {
83
                    $notFoundCount++;
84
                }
85
                $em->flush();
86
            }
87
        }
88
        $output->writeln([
89
            'End of list',
90
            '',
91
            'Students in promo ' . $input->getArgument('promo') . ' : ' . count($users)
92
        ]);
93
        if ($input->getOption('all')) {
94
            $output->writeln([
95
                'Imported missing photos: ' . $updatedNoPhotoCount,
96
                'Not found photos: ' . $notFoundCount,
97
                'Replaced photos: ' . $updatedExistingPhotoCount,
98
            ]);
99
        }
100
        else {
101
            $output->writeln([
102
                'Missing photos in promo : ' . $noPhotoCount,
103
                'Imported missing photos: ' . $updatedNoPhotoCount,
104
                'Not found photos: ' . $notFoundCount,
105
                'Remaining missing photos: ' . ($noPhotoCount - $updatedNoPhotoCount),
106
            ]);
107
        }
108
    }
109
    // Compare un User uPont et un utilisateur Facebook et essaye de deviner si
110
    // ce sont les mêmes personnes
111
    private function isSimilar(User $user, array $member)
112
    {
113
        $percent = 0;
114
        similar_text($user->getFirstName() . ' ' . $user->getLastName(), $member['name'], $percent);
115
        return $percent;
116
    }
117
}
118