processExpiringSubscriptions()   A
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 8
nop 4
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @author Rafał Muszyński <[email protected]>
5
 * @copyright 2014 Sourcefabric z.ú.
6
 * @license http://www.gnu.org/licenses/gpl-3.0.txt
7
 */
8
namespace Newscoop\PaywallBundle\Services;
9
10
use Newscoop\Services\EmailService;
11
use Newscoop\NewscoopBundle\Services\SystemPreferencesService;
12
use Newscoop\Services\PlaceholdersService;
13
use Newscoop\Services\TemplatesService;
14
use Newscoop\PaywallBundle\Notifications\Emails;
15
use Newscoop\PaywallBundle\Meta\MetaSubscription;
16
use Doctrine\ORM\EntityManager;
17
use Newscoop\PaywallBundle\Events\PaywallEvents;
18
use Newscoop\EventDispatcher\Events\GenericEvent;
19
use Newscoop\PaywallBundle\Entity\UserSubscription;
20
use Newscoop\PaywallBundle\Entity\Order;
21
22
/**
23
 * Notifications service.
24
 */
25
class NotificationsService
26
{
27
    /**
28
     * @var EmailService
29
     */
30
    protected $emailService;
31
32
    /**
33
     * @var SystemPreferencesService
34
     */
35
    protected $systemPreferences;
36
37
    /**
38
     * @var TemplatesService
39
     */
40
    protected $templatesService;
41
42
    /**
43
     * @var PlaceholdersService
44
     */
45
    protected $placeholdersService;
46
47
    /**
48
     * @var EntityManager
49
     */
50
    protected $em;
51
52
    protected $dispatcher;
53
54
    /**
55
     * @param EmailService                  $emailService
56
     * @param SystemPreferencesService      $systemPreferences
57
     * @param TemplatesService              $templatesService
58
     * @param PlaceholdersService           $placeholdersService
59
     * @param EntityManager                 $em
60
     * @param ContainerAwareEventDispatcher $dispatcher
61
     */
62
    public function __construct(
63
        EmailService $emailService,
64
        SystemPreferencesService $systemPreferences,
65
        TemplatesService $templatesService,
66
        PlaceholdersService $placeholdersService,
67
        EntityManager $em,
68
        $dispatcher
69
    ) {
70
        $this->emailService = $emailService;
71
        $this->systemPreferences = $systemPreferences;
72
        $this->templatesService = $templatesService;
73
        $this->placeholdersService = $placeholdersService;
74
        $this->em = $em;
75
        $this->dispatcher = $dispatcher;
76
    }
77
78
    /**
79
     * Sends email notifications.
80
     *
81
     * @param string                                $code             Email message type
82
     * @param Newscoop\Entity\User                  $user             User object
0 ignored issues
show
Bug introduced by
There is no parameter named $user. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
83
     * @param PaywallBundle\Entity\UserSubscription $userSubscription User's subscription
0 ignored issues
show
Bug introduced by
There is no parameter named $userSubscription. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
84
     */
85
    public function sendNotification($code, array $recipients = array(), array $data = array())
86
    {
87
        if ($this->systemPreferences->PaywallEmailNotifyEnabled != '1') {
88
            return;
89
        }
90
91
        $smarty = $this->templatesService->getSmarty();
92
        $smarty->assign('user', new \MetaUser($data['user']));
93
        $subscriptions = array();
94
        $order = new Order();
0 ignored issues
show
Unused Code introduced by
$order is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
95
        if (!$data['subscriptions'] instanceof UserSubscription) {
96
            $subscription = $data['subscriptions'][0];
97
            $order = $subscription->getOrder();
98
            foreach ($data['subscriptions'] as $key => $value) {
99
                $subscriptions[] = new MetaSubscription($value);
100
            }
101
102
            $smarty->assign('userSubscriptions', $subscriptions);
103
        } else {
104
            $subscription = $data['subscriptions'];
105
            $order = $subscription->getOrder();
106
            $smarty->assign('userSubscription', new MetaSubscription($subscription));
107
        }
108
109
        $smarty->assign('order', $order);
110
111
        try {
112
            $message = $this->loadProperMessageTemplateBy($code);
113
        } catch (\Exception $e) {
114
            throw new \Exception($e->getMessage());
115
        }
116
117
        $recipients = !empty($recipients) ? $recipients : $this->systemPreferences->PaywallMembershipNotifyEmail;
118
        $this->emailService->send(
119
            $this->placeholdersService->get('subject'),
120
            $message,
121
            $recipients,
122
            $this->systemPreferences->PaywallMembershipNotifyFromEmail
123
        );
124
    }
125
126
    private function loadProperMessageTemplateBy($code)
127
    {
128
        switch ($code) {
129
            case Emails::USER_CONFIRMATION:
130
                $message = $this->templatesService->fetchTemplate(
131
                    '_paywall/email_notify_user.tpl'
132
                );
133
                break;
134
            case Emails::SUBSCRIPTION_CONFIRMATION:
135
                $message = $this->templatesService->fetchTemplate(
136
                    '_paywall/email_notify_admin.tpl'
137
                );
138
                break;
139
            case Emails::SUBSCRIPTION_STATUS:
140
                $message = $this->templatesService->fetchTemplate(
141
                    '_paywall/email_subscription_status.tpl'
142
                );
143
                break;
144
            case Emails::SUBSCRIPTION_EXPIRATION:
145
                $message = $this->templatesService->fetchTemplate(
146
                    '_paywall/email_subscription_expiration.tpl'
147
                );
148
                break;
149
            case Emails::ADMIN_CREATED_CONFIRMATION:
150
                $message = $this->templatesService->fetchTemplate(
151
                    '_paywall/email_subscription_admin_created.tpl'
152
                );
153
                break;
154
            default:
155
                break;
156
        }
157
158
        return $message;
0 ignored issues
show
Bug introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
159
    }
160
161
    /**
162
     * Sets notify sent flag for given user subscription.
163
     * Level one of the notifications, for instance,
164
     * sends notifications 7 days before expiration.
165
     *
166
     * @param UserSubscription $subscription User subscription
167
     * @param \DateTime        $datetime     Date time when notify has been sent
168
     */
169
    public function setSentDateTimeOnLevelOne(UserSubscription $subscription, $datetime = null)
170
    {
171
        $subscription->setNotifySentLevelOne($datetime ?: new \DateTime('now'));
172
        $this->em->flush();
173
    }
174
175
    /**
176
     * Sets notify sent flag for given user subscription.
177
     * Level two of the notifications, for instance,
178
     * sends notifications 3 days before expiration.
179
     *
180
     * @param UserSubscription $subscription User subscription
181
     * @param \DateTime        $datetime     Date time when notify has been sent
182
     */
183
    public function setSentDateTimeOnLevelTwo(UserSubscription $subscription, $datetime = null)
184
    {
185
        $subscription->setNotifySentLevelTwo($datetime ?: new \DateTime('now'));
186
        $this->em->flush();
187
    }
188
189
    /**
190
     * Processes expiring subscriptions and sends email
191
     * notifications to users.
192
     *
193
     * @param \DateTime $now                Current date time
194
     * @param int       $subscriptionsCount Subscriptions count
0 ignored issues
show
Bug introduced by
There is no parameter named $subscriptionsCount. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
195
     */
196
    public function processExpiringSubscriptions($now, $notify, $count = 0, $days = 7)
197
    {
198
        if ($count === 0) {
199
            $count = $this->getExpiringSubscriptionsCount($now);
0 ignored issues
show
Bug introduced by
The call to getExpiringSubscriptionsCount() misses a required argument $notify.

This check looks for function calls that miss required arguments.

Loading history...
200
        }
201
202
        $batch = 100;
203
        $steps = ($count > $batch) ? ceil($count / $batch) : 1;
204
        for ($i = 0; $i < $steps; ++$i) {
205
            $offset = $i * $batch;
206
207
            $query = $this->em->getRepository('Newscoop\PaywallBundle\Entity\UserSubscription')
208
                ->getExpiringSubscriptions($offset, $batch, $now, $notify, $days);
209
210
            $expiringSubscriptions = $query->getResult();
211
            $this->dispatchNotificationSend($expiringSubscriptions);
212
        }
213
    }
214
215
    /**
216
     * Gets expiring subscriptions count.
217
     *
218
     * @param \DateTime $now Current date time
219
     *
220
     * @return int
221
     */
222
    public function getExpiringSubscriptionsCount($now, $notify, $days = 7)
223
    {
224
        $query = $this->em->getRepository('Newscoop\PaywallBundle\Entity\UserSubscription')
225
            ->getExpiringSubscriptionsCount($now, $notify, $days);
226
227
        return (int) $query->getSingleScalarResult();
228
    }
229
230
    private function dispatchNotificationSend($expiringSubscriptions)
231
    {
232
        foreach ($expiringSubscriptions as $key => $subscription) {
233
            $this->dispatcher->dispatch(
234
                PaywallEvents::SUBSCRIPTION_EXPIRATION,
235
                new GenericEvent($subscription)
236
            );
237
        }
238
    }
239
}
240