Passed
Pull Request — master (#193)
by
unknown
20:53
created

org_openpsa_invoices_scheduler::calculate_cycles()   B

Complexity

Conditions 7
Paths 26

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7.0084

Importance

Changes 0
Metric Value
cc 7
eloc 17
nc 26
nop 2
dl 0
loc 30
ccs 17
cts 18
cp 0.9444
crap 7.0084
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package org.openpsa.invoices
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
/**
10
 * Helper class to process subscription invoicing
11
 *
12
 * @package org.openpsa.invoices
13
 */
14
class org_openpsa_invoices_scheduler extends midcom_baseclasses_components_purecode
15
{
16
    /**
17
     * The deliverable we're processing
18
     *
19
     * @var org_openpsa_sales_salesproject_deliverable_dba
20
     */
21
    private $_deliverable;
22
23
    /**
24
     * The day of month on which subscriptions are invoiced (if none is set, they are invoiced continously)
25
     *
26
     * @var int
27
     */
28
    private $subscription_day;
29
30 36
    public function __construct(org_openpsa_sales_salesproject_deliverable_dba $deliverable)
31
    {
32 36
        parent::__construct();
33 36
        $this->_deliverable = $deliverable;
34 36
        $this->subscription_day = midcom_baseclasses_components_configuration::get('org.openpsa.sales', 'config')->get('subscription_invoice_day_of_month');
35 36
    }
36
37
    /**
38
     * Initiates a new subscription cycle and registers a midcom.services.at call for the next cycle.
39
     *
40
     * The subscription cycles rely on midcom.services.at. I'm not sure if it is wise to rely on it for such
41
     * a totally mission critical part of OpenPSA. Some safeguards might be wise to add.
42
     */
43 8
    public function run_cycle($cycle_number, $send_invoice = true)
44
    {
45 8
        if (time() < $this->_deliverable->start) {
46 1
            debug_add('Subscription hasn\'t started yet, register the start-up event to $start');
47 1
            return $this->_create_at_entry($cycle_number, $this->_deliverable->start);
48
        }
49
50 7
        debug_add('Running cycle ' . $cycle_number . ' for deliverable "' . $this->_deliverable->title . '"');
51
52 7
        $this_cycle_start = $this->get_cycle_start($cycle_number, time());
53 7
        if ($this->subscription_day && $cycle_number == 1) {
54
            // If there's a fixed day for invoicing, get_cycle_start already picked a future date for cycle 1
55 1
            $next_cycle_start = $this_cycle_start + 2; // +2 so we don't get overlaps in task
56
        } else {
57 7
            $next_cycle_start = $this->calculate_cycle_next($this_cycle_start);
58
        }
59 7
        $product = org_openpsa_products_product_dba::get_cached($this->_deliverable->product);
60
61 7
        if ($this->_deliverable->state < org_openpsa_sales_salesproject_deliverable_dba::STATE_STARTED) {
62 2
            $this->_deliverable->state = org_openpsa_sales_salesproject_deliverable_dba::STATE_STARTED;
63 2
            $this->_deliverable->update();
64
        }
65
66 7
        if ($send_invoice) {
67 7
            $calculator = new org_openpsa_invoices_calculator();
68 7
            $this_cycle_amount = $calculator->process_deliverable($this->_deliverable, $cycle_number);
69
        }
70
71 7
        $tasks_completed = [];
72 7
        $tasks_not_completed = [];
73
74 7
        if ($product->orgOpenpsaObtype == org_openpsa_products_product_dba::TYPE_SERVICE) {
0 ignored issues
show
Bug Best Practice introduced by
The property orgOpenpsaObtype does not exist on midcom_core_dbaobject. Since you implemented __get, consider adding a @property annotation.
Loading history...
75
            // Close previous task(s)
76 2
            $last_task = null;
77
78 2
            $qb = org_openpsa_projects_task_dba::new_query_builder();
79 2
            $qb->add_constraint('agreement', '=', $this->_deliverable->id);
80 2
            $qb->add_constraint('status', '<', org_openpsa_projects_task_status_dba::COMPLETED);
81
82 2
            foreach ($qb->execute() as $task) {
83 2
                if (org_openpsa_projects_workflow::complete($task, sprintf($this->_i18n->get_string('completed by subscription %s', 'org.openpsa.sales'), $cycle_number))) {
84 2
                    $tasks_completed[] = $task;
85
                } else {
86
                    $tasks_not_completed[] = $task;
87
                }
88 2
                $last_task = $task;
89
            }
90
91
            // Create task for the duration of this cycle
92 2
            $task_title = sprintf('%s %s', $this->_deliverable->title, $this->get_cycle_identifier($this_cycle_start));
0 ignored issues
show
Bug introduced by
It seems like $this->get_cycle_identifier($this_cycle_start) can also be of type false; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

92
            $task_title = sprintf('%s %s', $this->_deliverable->title, /** @scrutinizer ignore-type */ $this->get_cycle_identifier($this_cycle_start));
Loading history...
93 2
            $this->create_task($this_cycle_start, $next_cycle_start - 1, $task_title, $last_task);
94
        }
95
96
        // TODO: Warehouse management: create new order
97 7
        if (   $this->_deliverable->end < $next_cycle_start
98 7
            && $this->_deliverable->end != 0) {
99 1
            debug_add('Do not register next cycle, the contract ends before');
100 1
            return $this->_deliverable->end_subscription();
101
        }
102
103 7
        if (!$this->_create_at_entry($cycle_number + 1, $next_cycle_start)) {
104
            return false;
105
        }
106 7
        if ($send_invoice) {
107 7
            $this->_notify_owner($calculator, $cycle_number, $next_cycle_start, $this_cycle_amount, $tasks_completed, $tasks_not_completed);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $this_cycle_amount does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $calculator does not seem to be defined for all execution paths leading up to this point.
Loading history...
108
        }
109 7
        return true;
110
    }
111
112 8
    private function _create_at_entry($cycle_number, $start)
113
    {
114
        $args = [
115 8
            'deliverable' => $this->_deliverable->guid,
116 8
            'cycle'       => $cycle_number,
117
        ];
118 8
        $at_entry = new midcom_services_at_entry_dba();
119 8
        $at_entry->start = $start;
120 8
        $at_entry->component = 'org.openpsa.sales';
121 8
        $at_entry->method = 'new_subscription_cycle';
122 8
        $at_entry->arguments = $args;
123
124 8
        if (!$at_entry->create()) {
125
            debug_add('AT registration failed, last midgard error was: ' . midcom_connection::get_error_string(), MIDCOM_LOG_WARN);
126
            return false;
127
        }
128 8
        debug_add('AT entry for cycle ' . $cycle_number . ' created');
129 8
        org_openpsa_relatedto_plugin::create($at_entry, 'midcom.services.at', $this->_deliverable, 'org.openpsa.sales');
130 8
        return true;
131
    }
132
133 7
    private function _notify_owner($calculator, $cycle_number, $next_run, $invoiced_sum, $tasks_completed, $tasks_not_completed, $new_task = null)
134
    {
135 7
        $siteconfig = org_openpsa_core_siteconfig::get_instance();
136 7
        $message = [];
137 7
        $salesproject = org_openpsa_sales_salesproject_dba::get_cached($this->_deliverable->salesproject);
138
        try {
139 7
            $owner = midcom_db_person::get_cached($salesproject->owner);
0 ignored issues
show
Bug Best Practice introduced by
The property owner does not exist on midcom_core_dbaobject. Since you implemented __get, consider adding a @property annotation.
Loading history...
140
        } catch (midcom_error $e) {
141
            $e->log();
142
            return;
143
        }
144 7
        $customer = $salesproject->get_customer();
0 ignored issues
show
Bug introduced by
The method get_customer() does not exist on midcom_core_dbaobject. It seems like you code against a sub-type of midcom_core_dbaobject such as org_openpsa_invoices_invoice_dba or org_openpsa_sales_salesproject_dba. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

144
        /** @scrutinizer ignore-call */ 
145
        $customer = $salesproject->get_customer();
Loading history...
145 7
        $l10n = $this->_i18n->get_l10n('org.openpsa.sales');
146 7
        if (is_null($next_run)) {
147
            $next_run_label = $l10n->get('no more cycles');
148
        } else {
149 7
            $next_run_label = $l10n->get_formatter()->date($next_run);
150
        }
151
152
        // Title for long notifications
153 7
        $message['title'] = sprintf($l10n->get('subscription cycle %d closed for agreement %s (%s)'), $cycle_number, $this->_deliverable->title, $customer->get_label());
154
155
        // Content for long notifications
156 7
        $message['content'] = "{$message['title']}\n\n";
157 7
        $message['content'] .= $l10n->get('invoiced') . ": {$invoiced_sum}\n\n";
158
159 7
        if ($invoiced_sum > 0) {
160 4
            $invoice = $calculator->get_invoice();
161 4
            $message['content'] .= $this->_l10n->get('invoice') . " {$invoice->number}:\n";
162 4
            $url = $siteconfig->get_node_full_url('org.openpsa.invoices');
163 4
            $message['content'] .= $url . 'invoice/' . $invoice->guid . "/\n\n";
0 ignored issues
show
Bug introduced by
Are you sure $url of type null|mixed|false can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
            $message['content'] .= /** @scrutinizer ignore-type */ $url . 'invoice/' . $invoice->guid . "/\n\n";
Loading history...
164
        }
165
166 7
        if (count($tasks_completed) > 0) {
167 2
            $message['content'] .= "\n" . $l10n->get('tasks completed') . ":\n";
168
169 2
            foreach ($tasks_completed as $task) {
170 2
                $message['content'] .= "{$task->title}: {$task->reportedHours}h\n";
171
            }
172
        }
173
174 7
        if (count($tasks_not_completed) > 0) {
175
            $message['content'] .= "\n" . $l10n->get('tasks not completed') . ":\n";
176
177
            foreach ($tasks_not_completed as $task) {
178
                $message['content'] .= "{$task->title}: {$task->reportedHours}h\n";
179
            }
180
        }
181
182 7
        if ($new_task) {
183
            $message['content'] .= "\n" . $l10n->get('created new task') . ":\n";
184
            $message['content'] .= "{$task->title}\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $task does not seem to be defined for all execution paths leading up to this point.
Loading history...
185
        }
186
187 7
        $message['content'] .= "\n" . $l10n->get('next run') . ": {$next_run_label}\n\n";
188 7
        $message['content'] .= $this->_i18n->get_string('agreement', 'org.openpsa.projects') . ":\n";
189
190 7
        $url = $siteconfig->get_node_full_url('org.openpsa.sales');
191 7
        $message['content'] .= $url . 'deliverable/' . $this->_deliverable->guid . '/';
192
193
        // Content for short notifications
194 7
        $message['abstract'] = sprintf($l10n->get('%s: closed subscription cycle %d for agreement %s. invoiced %d. next cycle %s'), $customer->get_label(), $cycle_number, $this->_deliverable->title, $invoiced_sum, $next_run_label);
195
196
        // Send the message out
197 7
        org_openpsa_notifications::notify('org.openpsa.sales:new_subscription_cycle', $owner->guid, $message);
198 7
    }
199
200
    /**
201
     * @todo Check if we already have an open task for this delivery?
202
     */
203 3
    public function create_task($start, $end, $title, $source_task = null)
204
    {
205 3
        $salesproject = org_openpsa_sales_salesproject_dba::get_cached($this->_deliverable->salesproject);
206
207
        // Check if we already have a project for the sales project
208 3
        $project = $salesproject->get_project();
0 ignored issues
show
Bug introduced by
The method get_project() does not exist on midcom_core_dbaobject. Did you maybe mean get_parent()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
        /** @scrutinizer ignore-call */ 
209
        $project = $salesproject->get_project();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
209
210
        // Create the task
211 3
        $task = new org_openpsa_projects_task_dba();
212 3
        $task->agreement = $this->_deliverable->id;
213 3
        $task->customer = $salesproject->customer;
0 ignored issues
show
Bug Best Practice introduced by
The property customer does not exist on midcom_core_dbaobject. Since you implemented __get, consider adding a @property annotation.
Loading history...
214 3
        $task->title = $title;
215 3
        $task->description = $this->_deliverable->description;
216 3
        $task->start = $start;
217 3
        $task->end = $end;
218 3
        $task->plannedHours = $this->_deliverable->plannedUnits;
219
220 3
        $task->manager = $salesproject->owner;
0 ignored issues
show
Bug Best Practice introduced by
The property owner does not exist on midcom_core_dbaobject. Since you implemented __get, consider adding a @property annotation.
Loading history...
221 3
        if ($project) {
222 3
            $task->project = $project->id;
223 3
            $task->orgOpenpsaAccesstype = $project->orgOpenpsaAccesstype;
224 3
            $task->orgOpenpsaOwnerWg = $project->orgOpenpsaOwnerWg;
225
        }
226
227 3
        if (!empty($source_task)) {
228 3
            $task->priority = $source_task->priority;
229 3
            $task->manager = $source_task->manager;
230
        }
231
232
        // TODO: Figure out if we really want to keep this
233 3
        $task->hoursInvoiceableDefault = true;
234 3
        if (!$task->create()) {
235
            throw new midcom_error("The task for this cycle could not be created. Last Midgard error was: " . midcom_connection::get_error_string());
236
        }
237 3
        $task->add_members('contacts', array_keys($salesproject->contacts));
0 ignored issues
show
Bug Best Practice introduced by
The property contacts does not exist on midcom_core_dbaobject. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
It seems like $salesproject->contacts can also be of type null; however, parameter $input of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

237
        $task->add_members('contacts', array_keys(/** @scrutinizer ignore-type */ $salesproject->contacts));
Loading history...
238 3
        if (!empty($source_task)) {
239 3
            $source_task->get_members();
240 3
            $task->add_members('resources', array_keys($source_task->resources));
241
        }
242
243
        // Copy tags from deliverable so we can seek resources
244 3
        $tagger = new net_nemein_tag_handler();
245 3
        $tagger->copy_tags($this->_deliverable, $task);
246
247 3
        midcom::get()->uimessages->add($this->_i18n->get_string('org.openpsa.sales', 'org.openpsa.sales'), sprintf($this->_i18n->get_string('created task "%s"', 'org.openpsa.sales'), $task->title));
248 3
        return $task;
249
    }
250
251
    /**
252
     * Calculcate remaining cycles until salesproject's end or the specified number of months passes
253
     *
254
     * @param integer $months The maximum number of months to look forward
255
     * @param integer $start The timestamp from which to begin
256
     * @return integer
257
     */
258 15
    public function calculate_cycles($months = null, $start = null)
259
    {
260 15
        if ($start === null) {
261 9
            $start = time();
262
        }
263 15
        $cycles = 0;
264 15
        $cycle_time = $this->_deliverable->start;
265 15
        $end_time = $this->_deliverable->end;
266
267
        // This takes care of invalid/unsupported unit configs
268 15
        if ($this->calculate_cycle_next($cycle_time) === false) {
269
            return $cycles;
270
        }
271
272 15
        while ($cycle_time < $start) {
273 8
            $cycle_time = $this->calculate_cycle_next($cycle_time);
274
        }
275
276 15
        if (!is_null($months)) {
277 10
            $end_time = mktime(date('H', $cycle_time), date('m', $cycle_time), date('i', $cycle_time), date('m', $cycle_time) + $months, date('d', $cycle_time), date('Y', $cycle_time));
0 ignored issues
show
Bug introduced by
date('m', $cycle_time) of type string is incompatible with the type integer expected by parameter $minute of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
            $end_time = mktime(date('H', $cycle_time), /** @scrutinizer ignore-type */ date('m', $cycle_time), date('i', $cycle_time), date('m', $cycle_time) + $months, date('d', $cycle_time), date('Y', $cycle_time));
Loading history...
Bug introduced by
date('Y', $cycle_time) of type string is incompatible with the type integer expected by parameter $year of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
            $end_time = mktime(date('H', $cycle_time), date('m', $cycle_time), date('i', $cycle_time), date('m', $cycle_time) + $months, date('d', $cycle_time), /** @scrutinizer ignore-type */ date('Y', $cycle_time));
Loading history...
Bug introduced by
date('d', $cycle_time) of type string is incompatible with the type integer expected by parameter $day of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
            $end_time = mktime(date('H', $cycle_time), date('m', $cycle_time), date('i', $cycle_time), date('m', $cycle_time) + $months, /** @scrutinizer ignore-type */ date('d', $cycle_time), date('Y', $cycle_time));
Loading history...
Bug introduced by
date('H', $cycle_time) of type string is incompatible with the type integer expected by parameter $hour of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
            $end_time = mktime(/** @scrutinizer ignore-type */ date('H', $cycle_time), date('m', $cycle_time), date('i', $cycle_time), date('m', $cycle_time) + $months, date('d', $cycle_time), date('Y', $cycle_time));
Loading history...
Bug introduced by
date('i', $cycle_time) of type string is incompatible with the type integer expected by parameter $second of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
            $end_time = mktime(date('H', $cycle_time), date('m', $cycle_time), /** @scrutinizer ignore-type */ date('i', $cycle_time), date('m', $cycle_time) + $months, date('d', $cycle_time), date('Y', $cycle_time));
Loading history...
Bug introduced by
It seems like $cycle_time can also be of type false; however, parameter $timestamp of date() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
            $end_time = mktime(date('H', /** @scrutinizer ignore-type */ $cycle_time), date('m', $cycle_time), date('i', $cycle_time), date('m', $cycle_time) + $months, date('d', $cycle_time), date('Y', $cycle_time));
Loading history...
278
        }
279
280 15
        $cycles = 0;
281 15
        while ($cycle_time < $end_time) {
282 15
            $cycle_time = $this->calculate_cycle_next($cycle_time);
283 15
            if ($cycle_time <= $end_time) {
284 15
                $cycles++;
285
            }
286
        }
287 15
        return $cycles;
288
    }
289
290 24
    public function calculate_cycle_next($time)
291
    {
292 24
        switch ($this->_deliverable->unit) {
293 24
            case 'd':
294
                // Daily recurring subscription
295 3
                $new_date = new DateTime('+1 day ' . gmdate('Y-m-d', $time), new DateTimeZone('GMT'));
296 3
                break;
297 21
            case 'm':
298
                // Monthly recurring subscription
299 14
                $new_date = $this->_add_month($time, 1);
300 14
                break;
301 7
            case 'q':
302
                // Quarterly recurring subscription
303 3
                $new_date = $this->_add_month($time, 3);
304 3
                break;
305 4
            case 'hy':
306
                // Half-yearly recurring subscription
307 1
                $new_date = $this->_add_month($time, 6);
308 1
                break;
309 3
            case 'y':
310
                // Yearly recurring subscription
311 2
                $new_date = new DateTime('+1 year ' . gmdate('Y-m-d', $time), new DateTimeZone('GMT'));
312 2
                break;
313
            default:
314 1
                debug_add('Unrecognized unit value "' . $this->_deliverable->unit . '" for deliverable ' . $this->_deliverable->guid . ", returning false", MIDCOM_LOG_WARN);
315 1
                return false;
316
        }
317 23
        if ($this->_deliverable->unit != 'd') {
318
            //If previous cycle was run at the end of the month, the new one should be at the end of the month as well
319 20
            $date = new DateTime(gmdate('Y-m-d', $time), new DateTimeZone('GMT'));
320 20
            if (   $date->format('t') == $date->format('j')
321 20
                && $new_date->format('t') != $new_date->format('j')) {
322 5
                $new_date->setDate((int) $new_date->format('Y'), (int) $new_date->format('m'), (int) $new_date->format('t'));
323
            }
324
        }
325 23
        return (int) $new_date->format('U');
326
    }
327
328
    /**
329
     * Workaround for odd PHP DateTime behavior where for example
330
     * 2012-10-31 + 1 month would return 2012-12-01. This function makes
331
     * sure the new date is always in the expected month (so in the example above
332
     * it would return 2012-11-30)
333
     *
334
     * @param integer $time Original timestamp
335
     * @param integer $offset number of months to add
336
     * @return DateTime The new date object
337
     */
338 18
    private function _add_month($time, $offset)
339
    {
340 18
        $orig = new DateTime(gmdate('Y-m-d', $time), new DateTimeZone('GMT'));
341 18
        $new_date = clone $orig;
342 18
        $new_date->modify('+' . $offset . ' months');
343 18
        $control = clone $new_date;
344 18
        $control->modify('-' . $offset . ' months');
345
346 18
        while ($orig->format('m') !== $control->format('m')) {
347 4
            $new_date->modify('-1 day');
348 4
            $control = clone $new_date;
349 4
            $control->modify('-' . $offset . ' months');
350
        }
351
352 18
        return $new_date;
353
    }
354
355 10
    public function get_cycle_start($cycle_number, $time)
356
    {
357 10
        if ($cycle_number == 1) {
358 7
            if ($this->subscription_day) {
359 4
                return gmmktime(0, 0, 0, date('n', $time) + 1, $this->subscription_day, date('Y', $time));
0 ignored issues
show
Bug introduced by
date('Y', $time) of type string is incompatible with the type integer expected by parameter $year of gmmktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

359
                return gmmktime(0, 0, 0, date('n', $time) + 1, $this->subscription_day, /** @scrutinizer ignore-type */ date('Y', $time));
Loading history...
360
            }
361
362
            // no explicit day of month set for invoicing, use the deliverable start date
363 3
            return $this->_deliverable->start;
364
        }
365
366
        // cycle number > 1
367 4
        return $time;
368
    }
369
370 7
    public function get_cycle_identifier($time)
371
    {
372 7
        $date = new DateTime(gmdate('Y-m-d', $time), new DateTimeZone('GMT'));
373
374 7
        switch ($this->_deliverable->unit) {
375 7
            case 'd':
376
                // Daily recurring subscription
377 1
                $identifier = $date->format('Y-m-d');
378 1
                break;
379 6
            case 'm':
380
                // Monthly recurring subscription
381 3
                $identifier = $date->format('Y-m');
382 3
                break;
383 3
            case 'q':
384
                // Quarterly recurring subscription
385 1
                $identifier = ceil(((int)$date->format('n')) / 4) . 'Q' . $date->format('y');
386 1
                break;
387 2
            case 'hy':
388
                // Half-yearly recurring subscription
389 1
                $identifier = ceil(((int)$date->format('n')) / 6) . '/' . $date->format('Y');
390 1
                break;
391 1
            case 'y':
392
                // Yearly recurring subscription
393 1
                $identifier = $date->format('Y');
394 1
                break;
395
            default:
396
                debug_add('Unrecognized unit value "' . $this->_deliverable->unit . '" for deliverable ' . $this->_deliverable->guid . ", returning false", MIDCOM_LOG_WARN);
397
                return false;
398
        }
399
400 7
        return $identifier;
401
    }
402
}
403