Completed
Push — master ( 7b9f4b...1cd743 )
by Andreas
13s queued 10s
created

Tools/Console/Command/Schema/AbstractCommand.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\Schema;
6
7
use Doctrine\ODM\MongoDB\DocumentManager;
8
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
9
use Doctrine\ODM\MongoDB\SchemaManager;
10
use MongoDB\Driver\WriteConcern;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Exception\InvalidOptionException;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use function is_numeric;
16
use function is_string;
17
18
abstract class AbstractCommand extends Command
19
{
20
    public const DB         = 'db';
21
    public const COLLECTION = 'collection';
22
    public const INDEX      = 'index';
23
24
    protected function configure()
25
    {
26
        parent::configure();
27
28
        $this
29
            ->addOption('maxTimeMs', null, InputOption::VALUE_REQUIRED, 'An optional maxTimeMs that will be used for all schema operations.')
30
            ->addOption('w', null, InputOption::VALUE_REQUIRED, 'An optional w option for the write concern that will be used for all schema operations.')
31
            ->addOption('wTimeout', null, InputOption::VALUE_REQUIRED, 'An optional wTimeout option for the write concern that will be used for all schema operations. Using this option without a w option will cause an exception to be thrown.')
32
            ->addOption('journal', null, InputOption::VALUE_REQUIRED, 'An optional journal option for the write concern that will be used for all schema operations. Using this option without a w option will cause an exception to be thrown.');
33
    }
34
35
    abstract protected function processDocumentCollection(SchemaManager $sm, string $document, ?int $maxTimeMs, ?WriteConcern $writeConcern);
36
37
    abstract protected function processCollection(SchemaManager $sm, ?int $maxTimeMs, ?WriteConcern $writeConcern);
38
39
    abstract protected function processDocumentDb(SchemaManager $sm, string $document, ?int $maxTimeMs, ?WriteConcern $writeConcern);
40
41
    abstract protected function processDb(SchemaManager $sm, ?int $maxTimeMs, ?WriteConcern $writeConcern);
42
43
    abstract protected function processDocumentIndex(SchemaManager $sm, string $document, ?int $maxTimeMs, ?WriteConcern $writeConcern);
44
45
    abstract protected function processIndex(SchemaManager $sm, ?int $maxTimeMs, ?WriteConcern $writeConcern);
46
47
    /**
48
     * @return SchemaManager
49
     */
50
    protected function getSchemaManager()
51
    {
52
        return $this->getDocumentManager()->getSchemaManager();
53
    }
54
55
    /**
56
     * @return DocumentManager
57
     */
58
    protected function getDocumentManager()
59
    {
60
        return $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...
61
    }
62
63
    /**
64
     * @return ClassMetadataFactory
65
     */
66
    protected function getMetadataFactory()
67
    {
68
        return $this->getDocumentManager()->getMetadataFactory();
69
    }
70
71
    protected function getMaxTimeMsFromInput(InputInterface $input) : ?int
72
    {
73
        $maxTimeMs = $input->getOption('maxTimeMs');
74
75
        return is_string($maxTimeMs) ? (int) $maxTimeMs : null;
76
    }
77
78
    protected function getWriteConcernFromInput(InputInterface $input) : ?WriteConcern
79
    {
80
        $w        = $input->getOption('w');
81
        $wTimeout = $input->getOption('wTimeout');
82
        $journal  = $input->getOption('journal');
83
84
        if (! is_string($w)) {
85
            if ($wTimeout !== null || $journal !== null) {
86
                throw new InvalidOptionException('The "wTimeout" or "journal" options can only be used when passing a "w" option.');
87
            }
88
89
            return null;
90
        }
91
92
        if (is_numeric($w)) {
93
            $w = (int) $w;
94
        }
95
96
        $wTimeout = is_string($wTimeout) ? (int) $wTimeout : 0;
97
        $journal  = is_string($journal) ? (bool) $journal : false;
98
99
        return new WriteConcern($w, $wTimeout, $journal);
100
    }
101
}
102