Completed
Push — master ( bde6a0...48fd94 )
by
unknown
13:22
created

LoadSalesFunnelData::isTransitionAllowed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace OroCRM\Bundle\DemoDataBundle\Migrations\Data\Demo\ORM;
4
5
use Symfony\Component\DependencyInjection\ContainerInterface;
6
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
7
use Symfony\Component\Security\Core\SecurityContext;
8
9
use Doctrine\Common\Collections\Criteria;
10
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
11
use Doctrine\Common\DataFixtures\AbstractFixture;
12
use Doctrine\Common\Persistence\ObjectManager;
13
use Doctrine\ORM\EntityManager;
14
15
use Oro\Bundle\WorkflowBundle\Model\WorkflowManager;
16
use Oro\Bundle\WorkflowBundle\Entity\WorkflowItem;
17
18
use OroCRM\Bundle\SalesBundle\Entity\Lead;
19
use OroCRM\Bundle\SalesBundle\Entity\Opportunity;
20
use OroCRM\Bundle\SalesBundle\Entity\SalesFunnel;
21
22
use Oro\Bundle\SecurityBundle\Authentication\Token\UsernamePasswordOrganizationToken;
23
use Oro\Bundle\OrganizationBundle\Entity\Organization;
24
use Oro\Bundle\UserBundle\Entity\User;
25
26
class LoadSalesFunnelData extends AbstractFixture implements ContainerAwareInterface, DependentFixtureInterface
27
{
28
    /** @var array */
29
    protected $probabilities = [0.2, 0.5, 0.8];
30
31
    /** @var ContainerInterface */
32
    protected $container;
33
34
    /** @var  User[] */
35
    protected $users;
36
37
    /** @var  Lead[] */
38
    protected $leads;
39
40
    /** @var  Opportunity[] */
41
    protected $opportunities;
42
43
    /** @var WorkflowManager */
44
    protected $workflowManager;
45
46
    /** @var  EntityManager */
47
    protected $em;
48
49
    /** @var Organization */
50
    protected $organization;
51
52
    /** @var SecurityContext */
53
    protected $securityContext;
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function getDependencies()
59
    {
60
        return [
61
            'OroCRM\Bundle\DemoDataBundle\Migrations\Data\Demo\ORM\LoadLeadsData',
62
            'OroCRM\Bundle\DemoDataBundle\Migrations\Data\Demo\ORM\LoadOpportunitiesData'
63
        ];
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    public function setContainer(ContainerInterface $container = null)
70
    {
71
        $this->container = $container;
72
        $this->workflowManager = $container->get('oro_workflow.manager');
0 ignored issues
show
Bug introduced by
It seems like $container is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
73
    }
74
75
    /**
76
     * {@inheritDoc}
77
     */
78
    public function load(ObjectManager $manager)
79
    {
80
        $this->organization = $this->container->get('doctrine')->getManager()
81
            ->getRepository('OroOrganizationBundle:Organization')->getFirst();
82
83
        $this->securityContext = $this->container->get('security.context');
84
85
        $this->initSupportingEntities($manager);
86
        $this->loadFlows();
87
    }
88
89
    /**
90
     * @param ObjectManager $manager
91
     */
92
    protected function initSupportingEntities(ObjectManager $manager = null)
93
    {
94
        if ($manager) {
95
            $this->em = $manager;
96
        }
97
98
        $this->users = $this->em->getRepository('OroUserBundle:User')->findAll();
99
        $this->leads = $this->getRandomEntityRecords('OroCRMSalesBundle:Lead');
100
        $this->opportunities = $this->getRandomEntityRecords('OroCRMSalesBundle:Opportunity');
101
    }
102
103
    /**
104
     * @param string $entityName
105
     * @param int $limit
106
     *
107
     * @return array
108
     */
109
    protected function getRandomEntityRecords($entityName, $limit = 25)
110
    {
111
        $repo = $this->em->getRepository($entityName);
112
113
        $entityIds = $repo->createQueryBuilder('e')
114
            ->select('e.id')
115
            ->getQuery()
116
            ->getScalarResult();
117
118
        if (count($entityIds) > $limit) {
119
            $rawList = [];
120
            foreach ($entityIds as $key => $value) {
121
                // due array_rand() will pick only keywords
122
                $rawList[$value['id']] = null;
123
            }
124
125
            $keyList = array_rand($rawList, $limit);
126
127
            $criteria = new Criteria();
128
            $criteria->where(Criteria::expr()->in('id', $keyList));
129
130
            $result = $repo->createQueryBuilder('e')
131
                ->addCriteria($criteria)
132
                ->getQuery()
133
                ->getResult();
134
        } else {
135
            $result = $repo->findAll();
136
        }
137
138
        return $result;
139
    }
140
141
    protected function loadFlows()
142
    {
143
        $randomUser = count($this->users) - 1;
144
145 View Code Duplication
        foreach ($this->leads as $lead) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
146
            $user = $this->users[mt_rand(0, $randomUser)];
147
            $this->setSecurityContext($user);
148
            $this->loadSalesFlows($lead, $user);
149
        }
150
        $this->flush($this->em);
151
152 View Code Duplication
        foreach ($this->opportunities as $opportunity) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
153
            $user = $this->users[mt_rand(0, $randomUser)];
154
            $this->setSecurityContext($user);
155
            $this->loadSalesFlows($opportunity, $user);
156
        }
157
        $this->flush($this->em);
158
    }
159
160
    /**
161
     * @param Lead | Opportunity $entity
162
     * @param User $owner
163
     */
164
    protected function loadSalesFlows($entity, $owner)
165
    {
166
        if ($entity instanceof Lead) {
167
            $step = 'start_from_lead';
168
            $parameters = ['lead' => $entity];
169
        } else {
170
            $step = 'start_from_opportunity';
171
            $parameters = ['opportunity' => $entity];
172
        }
173
174
        $parameters = array_merge(
175
            [
176
                'sales_funnel' => null,
177
                'sales_funnel_owner' => $owner,
178
                'sales_funnel_start_date' => new \DateTime('now'),
179
            ],
180
            $parameters
181
        );
182
183
        $salesFunnel = new SalesFunnel();
184
        $salesFunnel->setDataChannel($this->getReference('default_channel'));
185
        if (!$this->workflowManager->isStartTransitionAvailable(
186
            'b2b_flow_sales_funnel',
187
            $step,
188
            $salesFunnel,
189
            $parameters
190
        )) {
191
            return;
192
        }
193
194
        $salesFunnelItem = $this->workflowManager->startWorkflow(
195
            'b2b_flow_sales_funnel',
196
            $salesFunnel,
197
            $step,
198
            $parameters
199
        );
200
201
        $salesFunnelItem->getData()
202
            ->set('new_opportunity_name', $entity->getName())
203
            ->set('new_company_name', $entity->getName());
204
205
        if ($entity instanceof Lead && !$this->workflowManager->transitIfAllowed($salesFunnelItem, 'qualify')) {
0 ignored issues
show
Bug introduced by
The method transitIfAllowed() does not exist on Oro\Bundle\WorkflowBundle\Model\WorkflowManager. Did you maybe mean transit()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
206
            return;
207
        }
208
209
        if (rand(1, 100) > 10) {
210
            $salesFunnelItem->getData()
211
                ->set('budget_amount', mt_rand(10, 10000))
212
                ->set('customer_need', mt_rand(10, 10000))
213
                ->set('proposed_solution', mt_rand(10, 10000))
214
                ->set('probability', $this->probabilities[array_rand($this->probabilities)]);
215
216
            if ($this->workflowManager->transitIfAllowed($salesFunnelItem, 'develop') && $this->getRandomBoolean()) {
0 ignored issues
show
Bug introduced by
The method transitIfAllowed() does not exist on Oro\Bundle\WorkflowBundle\Model\WorkflowManager. Did you maybe mean transit()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
217
                $salesFunnelItem->getData()
218
                    ->set('close_revenue', mt_rand(10, 1000))
219
                    ->set('close_date', new \DateTime());
220
221
                if ($this->getRandomBoolean()) {
222
                    $this->workflowManager->transitIfAllowed($salesFunnelItem, 'close_as_won');
0 ignored issues
show
Bug introduced by
The method transitIfAllowed() does not exist on Oro\Bundle\WorkflowBundle\Model\WorkflowManager. Did you maybe mean transit()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
223
                } else {
224
                    $salesFunnelItem->getData()
225
                        ->set('close_reason_name', 'cancelled')
226
                        ->set('close_date', new \DateTime('now', new \DateTimeZone('UTC')));
227
                    $this->workflowManager->transitIfAllowed($salesFunnelItem, 'close_as_lost');
0 ignored issues
show
Bug introduced by
The method transitIfAllowed() does not exist on Oro\Bundle\WorkflowBundle\Model\WorkflowManager. Did you maybe mean transit()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
228
                }
229
            }
230
        }
231
    }
232
233
    /**
234
     * @return bool
235
     */
236
    protected function getRandomBoolean()
237
    {
238
        return (bool) mt_rand(0, 1);
239
    }
240
241
    /**
242
     * @param User $user
243
     */
244
    protected function setSecurityContext($user)
245
    {
246
        $token = new UsernamePasswordOrganizationToken($user, $user->getUsername(), 'main', $this->organization);
247
        $this->securityContext->setToken($token);
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Securi...rityContext::setToken() has been deprecated with message: since version 2.6, to be removed in 3.0. Use TokenStorageInterface::setToken() instead. {@inheritdoc}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
248
    }
249
250
    /**
251
     * Flush objects
252
     *
253
     * @param mixed $manager
254
     */
255
    private function flush($manager)
256
    {
257
        $manager->flush();
258
    }
259
}
260