Completed
Push — master ( a8fe50...bce26f )
by Maciej
13s
created

Tools/Console/Command/GenerateHydratorsCommand.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Tools\Console\Command;
6
7
use Doctrine\ODM\MongoDB\Tools\Console\MetadataFilter;
8
use Symfony\Component\Console;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputOption;
11
use const PHP_EOL;
12
use function count;
13
use function file_exists;
14
use function is_dir;
15
use function is_writable;
16
use function mkdir;
17
use function realpath;
18
use function sprintf;
19
20
/**
21
 * Command to (re)generate the hydrator classes used by doctrine.
22
 *
23
 */
24
class GenerateHydratorsCommand extends Console\Command\Command
25
{
26
    /**
27
     * @see Console\Command\Command
28
     */
29 View Code Duplication
    protected function configure()
30
    {
31
        $this
32
        ->setName('odm:generate:hydrators')
33
        ->setDescription('Generates hydrator classes for document classes.')
34
        ->setDefinition([
35
            new InputOption(
36
                'filter',
37
                null,
38
                InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
39
                'A string pattern used to match documents that should be processed.'
40
            ),
41
            new InputArgument(
42
                'dest-path',
43
                InputArgument::OPTIONAL,
44
                'The path to generate your hydrator classes. If none is provided, it will attempt to grab from configuration.'
45
            ),
46
        ])
47
        ->setHelp(<<<EOT
48
Generates hydrator classes for document classes.
49
EOT
50
        );
51
    }
52
53
    /**
54
     * @see Console\Command\Command
55
     */
56
    protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
57
    {
58
        $dm = $this->getHelper('documentManager')->getDocumentManager();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Symfony\Component\Console\Helper\HelperInterface as the method getDocumentManager() does only exist in the following implementations of said interface: Doctrine\ODM\MongoDB\Too...r\DocumentManagerHelper.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
59
60
        $metadatas = $dm->getMetadataFactory()->getAllMetadata();
61
        $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter'));
62
        $destPath = $input->getArgument('dest-path');
63
64
        // Process destination directory
65
        if ($destPath === null) {
66
            $destPath = $dm->getConfiguration()->getHydratorDir();
67
        }
68
69
        if (! is_dir($destPath)) {
70
            mkdir($destPath, 0775, true);
71
        }
72
73
        $destPath = realpath($destPath);
74
75 View Code Duplication
        if (! file_exists($destPath)) {
76
            throw new \InvalidArgumentException(
77
                sprintf("Hydrators destination directory '<info>%s</info>' does not exist.", $destPath)
78
            );
79
        } elseif (! is_writable($destPath)) {
80
            throw new \InvalidArgumentException(
81
                sprintf("Hydrators destination directory '<info>%s</info>' does not have write permissions.", $destPath)
82
            );
83
        }
84
85 View Code Duplication
        if (count($metadatas)) {
86
            foreach ($metadatas as $metadata) {
87
                $output->write(
88
                    sprintf('Processing document "<info>%s</info>"', $metadata->name) . PHP_EOL
89
                );
90
            }
91
92
            // Generating Hydrators
93
            $dm->getHydratorFactory()->generateHydratorClasses($metadatas, $destPath);
94
95
            // Outputting information message
96
            $output->write(PHP_EOL . sprintf('Hydrator classes generated to "<info>%s</INFO>"', $destPath) . PHP_EOL);
97
        } else {
98
            $output->write('No Metadata Classes to process.' . PHP_EOL);
99
        }
100
    }
101
}
102