GenerateEntityCommand::configure()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

Changes 6
Bugs 1 Features 1
Metric Value
c 6
b 1
f 1
dl 0
loc 15
ccs 12
cts 12
cp 1
rs 9.4285
cc 1
eloc 11
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Tpg\ExtjsBundle\Command;
4
5
use Doctrine\Bundle\DoctrineBundle\Mapping\ClassMetadataCollection;
6
use Doctrine\Bundle\DoctrineBundle\Mapping\DisconnectedMetadataFactory;
7
use Doctrine\ORM\Mapping\ClassMetadata;
8
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
/**
15
 * Generates Extjs model based on entity
16
 */
17
class GenerateEntityCommand extends ContainerAwareCommand
18
{
19
    /**
20
     * @inheritdoc
21
     */
22 2
    public function configure()
23
    {
24 2
        parent::configure();
25
26 2
        $this->setName('generate:extjs:entity');
27 2
        $this->addArgument('name', InputArgument::REQUIRED, "A bundle name, a namespace, or a class name");
28 2
        $this->addOption(
29 2
            'output',
30 2
            '',
31 2
            InputOption::VALUE_OPTIONAL,
32
            "File/Directory for the output of the ExtJs model file"
33 2
        );
34 2
        $this->addOption('overwrite', 'y', InputOption::VALUE_NONE, "Overwrite existing file");
35 2
        $this->setDescription("Generate Sencha ExtJs model base on an existing PHP entity");
36 2
    }
37
38
    /**
39
     * @inheritdoc
40
     */
41
    public function execute(InputInterface $input, OutputInterface $output)
42
    {
43
        $reader = $this->getContainer()->get('annotation_reader');
44
        $generator = $this->getContainer()->get("tpg_extjs.generator");
45
        $outputLocation = false;
46
        if ($input->getOption("output")) {
47
            if (is_dir($input->getOption("output"))) {
48
                $outputLocation = realpath($input->getOption("output"));
49
            } else {
50
                if (is_dir(dirname($input->getOption("output")))) {
51
                    if (!$this->canWriteFile($input, $output, $input->getOption("output"))) {
52
                        exit(1);
0 ignored issues
show
Coding Style Compatibility introduced by
The method execute() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
53
                    }
54
                    file_put_contents($input->getOption("output"), '');
55
                    $outputLocation = realpath($input->getOption("output"));
56
                } else {
57
                    $output->writeln("Invalid output directory");
58
                    exit(1);
0 ignored issues
show
Coding Style Compatibility introduced by
The method execute() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
59
                }
60
            }
61
        }
62
        $metadata = $this->getMetadata($input, $output, $outputLocation === false);
63
        foreach ($metadata->getMetadata() as $classMetadata) {
64
            /** @var ClassMetadata $classMetadata */
65
            $classMetadata->reflClass = new \ReflectionClass($classMetadata->name);
66
            if ($reader->getClassAnnotation(
67
                    $classMetadata->getReflectionClass(),
68
                    'Tpg\ExtjsBundle\Annotation\Model'
69
                ) !== null
70
            ) {
71
                if ($outputLocation) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $outputLocation of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
72
                    if (is_dir($outputLocation)) {
73
                        $baseDir = $outputLocation;
74
                        foreach (explode("\\", $classMetadata->namespace) as $dir) {
75
                            @mkdir($baseDir.DIRECTORY_SEPARATOR.$dir);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
76
                            $baseDir .= DIRECTORY_SEPARATOR.$dir;
77
                        }
78
                        $fileName = $baseDir.DIRECTORY_SEPARATOR.substr(
79
                                $classMetadata->name,
80
                                strlen($classMetadata->namespace) + 1
81
                            ).".js";
82
                        if (!$this->canWriteFile($input, $output, $fileName)) {
83
                            continue;
84
                        }
85
                        file_put_contents(
86
                            $fileName,
87
                            $generator->generateMarkupForEntity($classMetadata->name)
88
                        );
89
                        $output->writeln("Generated $fileName");
90
                    } else {
91
                        file_put_contents(
92
                            $outputLocation,
93
                            $generator->generateMarkupForEntity($classMetadata->name),
94
                            FILE_APPEND
95
                        );
96
                        $output->writeln("Appending to $outputLocation");
97
                    }
98
                } else {
99
                    $output->write($generator->generateMarkupForEntity($classMetadata->name));
100
                }
101
            }
102
        }
103
    }
104
105
    /**
106
     * Returning ClassMetadata
107
     *
108
     * @param InputInterface $input An InputInterface instance
109
     * @param OutputInterface $output An OutputInterface instance
110
     * @param bool $displayStatus Displaying process messages
111
     *
112
     * @return ClassMetadataCollection
113
     */
114
    protected function getMetadata(InputInterface $input, OutputInterface $output, $displayStatus)
115
    {
116
        $manager = new DisconnectedMetadataFactory($this->getContainer()->get('doctrine'));
117
        try {
118
            $bundle = $this->getContainer()->get("kernel")->getBundle($input->getArgument('name'));
119
            if ($displayStatus) {
120
                $output->writeln(sprintf('Generating entities for bundle "<info>%s</info>"', $bundle->getName()));
121
            }
122
            $metadata = $manager->getBundleMetadata($bundle);
123
        } catch (\InvalidArgumentException $e) {
124
            $name = strtr($input->getArgument('name'), '/', '\\');
125
126
            if (false !== $pos = strpos($name, ':')) {
127
                $name = $this->getContainer()->get('doctrine')
128
                        ->getAliasNamespace(substr($name, 0, $pos)).'\\'.substr($name, $pos + 1);
129
            }
130
131
            if (class_exists($name)) {
132
                if ($displayStatus) {
133
                    $output->writeln(sprintf('Generating entity "<info>%s</info>"', $name));
134
                }
135
                $metadata = $manager->getClassMetadata($name, $input->getOption('path'));
136
            } else {
137
                if ($displayStatus) {
138
                    $output->writeln(sprintf('Generating entities for namespace "<info>%s</info>"', $name));
139
                }
140
                $metadata = $manager->getNamespaceMetadata($name, $input->getOption('path'));
141
            }
142
        }
143
144
        return $metadata;
145
    }
146
147
    protected function canWriteFile(InputInterface $input, OutputInterface $output, $fileName)
148
    {
149
        if (!$input->getOption("overwrite") && file_exists($fileName)) {
150
            $dialog = $this->getHelperSet()->get('dialog');
151
            $result = $dialog->askConfirmation(
152
                $output,
153
                '<question>'.$fileName.' already exist, overwrite?</question>',
154
                false
155
            );
156
            if (!$result) {
157
                $output->writeln("Skipping $fileName");
158
            }
159
160
            return $result;
161
        } else {
162
            return true;
163
        }
164
    }
165
}