Calendar_Core::add_data()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
eloc 4
c 2
b 1
f 0
nc 2
nop 1
dl 0
loc 10
rs 9.4285
1
<?php defined('SYSPATH') or die('No direct access allowed.');
2
/**
3
 * Calendar creation library.
4
 *
5
 * $Id: Calendar.php 3769 2008-12-15 00:48:56Z zombor $
6
 *
7
 * @package    Calendar
8
 * @author     Kohana Team
9
 * @copyright  (c) 2007-2008 Kohana Team
10
 * @license    http://kohanaphp.com/license.html
11
 */
12
class Calendar_Core extends Event_Subject
13
{
14
15
    // Start the calendar on Sunday by default
16
    public static $start_monday = false;
17
18
    // Month and year to use for calendaring
19
    protected $month;
20
    protected $year;
21
22
    // Week starts on Sunday
23
    protected $week_start = 0;
24
25
    // Observed data
26
    protected $observed_data;
27
28
    /**
29
     * Returns an array of the names of the days, using the current locale.
30
     *
31
     * @param   integer  left of day names
32
     * @return  array
33
     */
34
    public static function days($length = true)
35
    {
36
        // strftime day format
37
        $format = ($length > 3) ? '%A' : '%a';
38
39
        // Days of the week
40
        $days = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
41
42
        if (Calendar::$start_monday === true) {
43
            // Push Sunday to the end of the days
44
            array_push($days, array_shift($days));
45
        }
46
47
        if (strpos(Kohana::config('locale.language.0'), 'en') !== 0) {
48
            // This is a bit awkward, but it works properly and is reliable
49
            foreach ($days as $i => $day) {
50
                // Convert the English names to i18n names
51
                $days[$i] = strftime($format, strtotime($day));
52
            }
53
        }
54
55
        if (is_int($length) or ctype_digit($length)) {
56
            foreach ($days as $i => $day) {
57
                // Shorten the days to the expected length
58
                $days[$i] = utf8::substr($day, 0, $length);
59
            }
60
        }
61
62
        return $days;
63
    }
64
65
    /**
66
     * Create a new Calendar instance. A month and year can be specified.
67
     * By default, the current month and year are used.
68
     *
69
     * @param   integer  month number
70
     * @param   integer  year number
71
     * @return  object
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Calendar.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
72
     */
73
    public static function factory($month = null, $year = null)
74
    {
75
        return new Calendar($month, $year);
76
    }
77
78
    /**
79
     * Create a new Calendar instance. A month and year can be specified.
80
     * By default, the current month and year are used.
81
     *
82
     * @param   integer  month number
83
     * @param   integer  year number
84
     * @return  void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
85
     */
86
    public function __construct($month = null, $year = null)
87
    {
88
        empty($month) and $month = date('n'); // Current month
89
        empty($year)  and $year  = date('Y'); // Current year
90
91
        // Set the month and year
92
        $this->month = (int) $month;
93
        $this->year  = (int) $year;
94
95
        if (Calendar::$start_monday === true) {
96
            // Week starts on Monday
97
            $this->week_start = 1;
98
        }
99
    }
100
101
    /**
102
     * Allows fetching the current month and year.
103
     *
104
     * @param   string  key to get
105
     * @return  mixed
106
     */
107
    public function __get($key)
108
    {
109
        if ($key === 'month' or $key === 'year') {
110
            return $this->$key;
111
        }
112
    }
113
114
    /**
115
     * Calendar_Event factory method.
116
     *
117
     * @param   string  unique name for the event
118
     * @return  object  Calendar_Event
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Calendar_Event.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
119
     */
120
    public function event($name = null)
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
121
    {
122
        return new Calendar_Event($this);
123
    }
124
125
    /**
126
     * Calendar_Event factory method.
127
     *
128
     * @chainable
129
     * @param   string  standard event type
130
     * @return  Calendar_Core
131
     */
132
    public function standard($name)
133
    {
134
        switch ($name) {
135
            case 'today':
136
                // Add an event for the current day
137
                $this->attach($this->event()->condition('timestamp', strtotime('today'))->add_class('today'));
138
            break;
139
            case 'prev-next':
140
                // Add an event for padding days
141
                $this->attach($this->event()->condition('current', false)->add_class('prev-next'));
142
            break;
143
            case 'holidays':
144
                // Base event
145
                $event = $this->event()->condition('current', true)->add_class('holiday');
146
147
                // Attach New Years
148
                $holiday = clone $event;
149
                $this->attach($holiday->condition('month', 1)->condition('day', 1));
150
151
                // Attach Valentine's Day
152
                $holiday = clone $event;
153
                $this->attach($holiday->condition('month', 2)->condition('day', 14));
154
155
                // Attach St. Patrick's Day
156
                $holiday = clone $event;
157
                $this->attach($holiday->condition('month', 3)->condition('day', 17));
158
159
                // Attach Easter
160
                $holiday = clone $event;
161
                $this->attach($holiday->condition('easter', true));
162
163
                // Attach Memorial Day
164
                $holiday = clone $event;
165
                $this->attach($holiday->condition('month', 5)->condition('day_of_week', 1)->condition('last_occurrence', true));
166
167
                // Attach Independance Day
168
                $holiday = clone $event;
169
                $this->attach($holiday->condition('month', 7)->condition('day', 4));
170
171
                // Attach Labor Day
172
                $holiday = clone $event;
173
                $this->attach($holiday->condition('month', 9)->condition('day_of_week', 1)->condition('occurrence', 1));
174
175
                // Attach Halloween
176
                $holiday = clone $event;
177
                $this->attach($holiday->condition('month', 10)->condition('day', 31));
178
179
                // Attach Thanksgiving
180
                $holiday = clone $event;
181
                $this->attach($holiday->condition('month', 11)->condition('day_of_week', 4)->condition('occurrence', 4));
182
183
                // Attach Christmas
184
                $holiday = clone $event;
185
                $this->attach($holiday->condition('month', 12)->condition('day', 25));
186
            break;
187
            case 'weekends':
188
                // Weekend events
189
                $this->attach($this->event()->condition('weekend', true)->add_class('weekend'));
190
            break;
191
        }
192
193
        return $this;
194
    }
195
196
    /**
197
     * Returns an array for use with a view. The array contains an array for
198
     * each week. Each week contains 7 arrays, with a day number and status:
199
     * TRUE if the day is in the month, FALSE if it is padding.
200
     *
201
     * @return  array
202
     */
203
    public function weeks()
204
    {
205
        // First day of the month as a timestamp
206
        $first = mktime(1, 0, 0, $this->month, 1, $this->year);
207
208
        // Total number of days in this month
209
        $total = (int) date('t', $first);
210
211
        // Last day of the month as a timestamp
212
        $last  = mktime(1, 0, 0, $this->month, $total, $this->year);
213
214
        // Make the month and week empty arrays
215
        $month = $week = array();
216
217
        // Number of days added. When this reaches 7, start a new week
218
        $days = 0;
219
        $week_number = 1;
220
221 View Code Duplication
        if (($w = (int) date('w', $first) - $this->week_start) < 0) {
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...
Comprehensibility introduced by
Avoid variables with short names like $w. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
222
            $w = 6;
223
        }
224
225
        if ($w > 0) {
226
            // Number of days in the previous month
227
            $n = (int) date('t', mktime(1, 0, 0, $this->month - 1, 1, $this->year));
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $n. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
228
229
            // i = number of day, t = number of days to pad
230
            for ($i = $n - $w + 1, $t = $w; $t > 0; $t--, $i++) {
231
                // Notify the listeners
232
                $this->notify(array($this->month - 1, $i, $this->year, $week_number, false));
233
234
                // Add previous month padding days
235
                $week[] = array($i, false, $this->observed_data);
236
                $days++;
237
            }
238
        }
239
240
        // i = number of day
241
        for ($i = 1; $i <= $total; $i++) {
242
            if ($days % 7 === 0) {
243
                // Start a new week
244
                $month[] = $week;
245
                $week = array();
246
247
                $week_number++;
248
            }
249
250
            // Notify the listeners
251
            $this->notify(array($this->month, $i, $this->year, $week_number, true));
252
253
            // Add days to this month
254
            $week[] = array($i, true, $this->observed_data);
255
            $days++;
256
        }
257
258 View Code Duplication
        if (($w = (int) date('w', $last) - $this->week_start) < 0) {
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...
259
            $w = 6;
260
        }
261
262
        if ($w >= 0) {
263
            // i = number of day, t = number of days to pad
264
            for ($i = 1, $t = 6 - $w; $t > 0; $t--, $i++) {
265
                // Notify the listeners
266
                $this->notify(array($this->month + 1, $i, $this->year, $week_number, false));
267
268
                // Add next month padding days
269
                $week[] = array($i, false, $this->observed_data);
270
            }
271
        }
272
273
        if (! empty($week)) {
274
            // Append the remaining days
275
            $month[] = $week;
276
        }
277
278
        return $month;
279
    }
280
281
    /**
282
     * Adds new data from an observer. All event data contains and array of CSS
283
     * classes and an array of output messages.
284
     *
285
     * @param   array  observer data.
286
     * @return  void
287
     */
288
    public function add_data(array $data)
289
    {
290
        // Add new classes
291
        $this->observed_data['classes'] += $data['classes'];
292
293
        if (! empty($data['output'])) {
294
            // Only add output if it's not empty
295
            $this->observed_data['output'][] = $data['output'];
296
        }
297
    }
298
299
    /**
300
     * Resets the observed data and sends a notify to all attached events.
301
     *
302
     * @param   array  UNIX timestamp
303
     * @return  void
304
     */
305
    public function notify($data)
306
    {
307
        // Reset observed data
308
        $this->observed_data = array(
309
            'classes' => array(),
310
            'output' => array(),
311
        );
312
313
        // Send a notify
314
        parent::notify($data);
315
    }
316
317
    /**
318
     * Convert the calendar to HTML using the kohana_calendar view.
319
     *
320
     * @return  string
321
     */
322
    public function render()
323
    {
324
        $view =  new View('kohana_calendar', array(
325
            'month'  => $this->month,
326
            'year'   => $this->year,
327
            'weeks'  => $this->weeks(),
328
        ));
329
330
        return $view->render();
331
    }
332
333
    /**
334
     * Magically convert this object to a string, the rendered calendar.
335
     *
336
     * @return  string
337
     */
338
    public function __toString()
339
    {
340
        return $this->render();
341
    }
342
} // End Calendar
343