Passed
Pull Request — master (#49)
by
unknown
13:21
created

AddCommand::execute()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 4
eloc 16
c 1
b 1
f 1
nc 6
nop 2
dl 0
loc 24
rs 9.7333
1
<?php
2
3
namespace App\Command\Fixture;
4
5
use App\Blog\Entity\Comment;
6
use App\Blog\Entity\Post;
7
use App\Blog\Entity\Tag;
8
use App\Entity\User;
9
use App\Blog\Tag\TagRepository;
10
use Cycle\ORM\ORMInterface;
11
use Cycle\ORM\Transaction;
12
use Faker\Factory;
13
use Faker\Generator;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use Symfony\Component\Console\Style\SymfonyStyle;
19
use Yiisoft\Yii\Console\ExitCode;
20
21
class AddCommand extends Command
22
{
23
    protected static $defaultName = 'fixture/add';
24
25
    private ORMInterface $orm;
26
    private Generator $faker;
27
    /** @var User[] */
28
    private array $users = [];
29
    /** @var Tag[] */
30
    private array $tags = [];
31
32
    private const DEFAULT_COUNT = 10;
33
34
    public function __construct(ORMInterface $orm)
35
    {
36
        parent::__construct();
37
        $this->orm = $orm;
38
    }
39
40
    public function configure(): void
41
    {
42
        $this
43
            ->setDescription('Add fixtures')
44
            ->setHelp('This command adds random content')
45
            ->addArgument('count', InputArgument::OPTIONAL, 'Count', self::DEFAULT_COUNT);
46
    }
47
48
    protected function execute(InputInterface $input, OutputInterface $output): int
49
    {
50
        $io = new SymfonyStyle($input, $output);
51
52
        $count = (int)$input->getArgument('count');
53
        // get faker
54
        if (!class_exists(Factory::class)) {
55
            $io->error('Faker should be installed. Run `composer install --dev`');
56
            return ExitCode::UNSPECIFIED_ERROR;
57
        }
58
        $this->faker = Factory::create();
59
60
        try {
61
            $this->addUsers($count);
62
            $this->addTags($count);
63
            $this->addPosts($count);
64
65
            $this->saveEntities();
66
        } catch (\Throwable $t) {
67
            $io->error($t->getMessage());
68
            return $t->getCode() ?: ExitCode::UNSPECIFIED_ERROR;
69
        }
70
        $io->success('Done');
71
        return ExitCode::OK;
72
    }
73
74
    private function saveEntities(): void
75
    {
76
        $transaction = new Transaction($this->orm);
77
        foreach ($this->users as $user) {
78
            $transaction->persist($user);
79
        }
80
        $transaction->run();
81
    }
82
83
    private function addUsers(int $count = self::DEFAULT_COUNT): void
84
    {
85
        for ($i = 0; $i <= $count; ++$i) {
86
            $user = new User();
87
            $user->setLogin($login = $this->faker->firstName . rand(0, 9999));
88
            $user->setPassword($login);
89
            $this->users[] = $user;
90
        }
91
    }
92
93
    private function addTags(int $count = self::DEFAULT_COUNT): void
94
    {
95
        /** @var TagRepository $tagRepository */
96
        $tagRepository = $this->orm->getRepository(Tag::class);
97
        $this->tags = [];
98
        $tagWords = [];
99
        for ($i = 0, $fails = 0; $i <= $count; ++$i) {
100
            $word = $this->faker->word();
101
            if (in_array($word, $tagWords, true)) {
102
                --$i;
103
                ++$fails;
104
                if ($fails >= $count) {
105
                    break;
106
                }
107
                continue;
108
            }
109
            $tagWords[] = $word;
110
            $tag = $tagRepository->getOrCreate($word);
111
            $this->tags[] = $tag;
112
        }
113
    }
114
115
    private function addPosts(int $count = self::DEFAULT_COUNT): void
116
    {
117
        if (count($this->users) === 0) {
118
            throw new \Exception('No users');
119
        }
120
        for ($i = 0; $i <= $count; ++$i) {
121
            /** @var User $postUser */
122
            $postUser = $this->users[array_rand($this->users)];
123
            $post = new Post($this->faker->text(64), $this->faker->realText(rand(1000, 4000)));
124
            $post->setUser($postUser);
125
            $postUser->addPost($post);
126
            $public = rand(0, 2) > 0;
127
            $post->setPublic($public);
128
            if ($public) {
129
                $post->setPublishedAt(new \DateTimeImmutable(date('r', rand(time(), strtotime('-2 years')))));
130
            }
131
            // link tags
132
            $postTags = (array)array_rand($this->tags, rand(1, count($this->tags)));
133
            foreach ($postTags as $tagId) {
134
                $post->addTag($this->tags[$tagId]);
135
            }
136
            // add comments
137
            $commentsCount = rand(0, $count);
138
            for ($j = 0; $j <= $commentsCount; ++$j) {
139
                $comment = new Comment($this->faker->realText(rand(100, 500)));
140
                $commentPublic = rand(0, 3) > 0;
141
                $comment->setPublic($commentPublic);
142
                if ($commentPublic) {
143
                    $comment->setPublishedAt(new \DateTimeImmutable(date('r', rand(time(), strtotime('-1 years')))));
144
                }
145
                $commentUser = $this->users[array_rand($this->users)];
146
                $comment->setUser($commentUser);
147
                $post->addComment($comment);
148
            }
149
        }
150
    }
151
}
152