diff --git a/composer.json b/composer.json index 0e9f482aa2..ed7034c5c3 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "require": { - "php-ffmpeg/php-ffmpeg": "0.3.x-dev@dev" + "php-ffmpeg/php-ffmpeg": "0.3.x-dev@dev", + "sabre/vobject" : "~3.1" } } diff --git a/main/admin/calendar.lib.php b/main/admin/calendar.lib.php index 2475b97ea8..1e18e741d5 100644 --- a/main/admin/calendar.lib.php +++ b/main/admin/calendar.lib.php @@ -1108,7 +1108,6 @@ function show_user_filter_form() /** @todo this select missing to implement */ -//$user_list=get_course_users(); echo " - february is from 1 to 28 (or 29) and not to 31 - - foreach (range(1, 31) as $i) { - // values have to have double digits - $value = ($i <= 9 ? '0'.$i : $i ); - // the current day is indicated with [] around the date - if ($value == $end_day) { - echo ""; - } else { - echo ""; - } - } - ?> - - - - - - 'vertical-align: middle;')), array('id' => 'end_date_calendar_icon')); ?> - -    - - - - - '; - - // Repeating the calendar item - if (empty($id)) { - //only show repeat fields when adding, not for editing an calendar item - echo '
- -
- -  '.get_lang('RepeatEvent').' - '; - ?> - - - - - - - - - - - - - - - -
'; - } - if (isset($agendaItem['all_day'])) { - $checked = null; - if ($agendaItem['all_day']) { - $checked = 'checked'; - } - echo '
- -
- '.get_lang('AllDay').' -
-
'; - } - //only show repeat fields if adding, not if editing - // the main area of the agenda item: the wysiwyg editor - echo '
- -
'; - require_once api_get_path(LIBRARY_PATH)."/fckeditor/fckeditor.php"; - $oFCKeditor = new FCKeditor('content'); - $oFCKeditor->Width = '100%'; - $oFCKeditor->Height = '200'; - if (!api_is_allowed_to_edit(null, true)) { - $oFCKeditor->ToolbarSet = 'AgendaStudent'; - } else { - $oFCKeditor->ToolbarSet = 'Agenda'; - } - $oFCKeditor->Value = $content; - $return = $oFCKeditor->CreateHtml(); - echo $return; - echo '
-
- -
-
'; - - if ($agendaObj->type == 'course') { - // File attachment - echo '
- -
- -
- -
- -
-
'; - } - // the submit button for storing the calendar item - echo '
- -
'; - if (isset($_GET['id'])) { - $class = 'save'; - $text = get_lang('ModifyEvent'); - } else { - $class = 'add'; - $text = get_lang('AgendaAdd'); - } - echo ''; - echo '
-
'; - ?> - - 0) { - $sqlquery = "SELECT - agenda.*, item_property.* - FROM ".$TABLEAGENDA." agenda, - ".$TABLE_ITEMPROPERTY." item_property - WHERE agenda.id = item_property.ref - AND MONTH(agenda.start_date)='".$month."' - AND YEAR(agenda.start_date)='".$year."' - AND item_property.tool='".TOOL_CALENDAR_EVENT."' - AND ( item_property.to_user_id='".api_get_user_id()."' OR item_property.to_group_id IN (0, ".implode(", ", $group_memberships).") ) - AND item_property.visibility='1' - ORDER BY start_date "; - } else { - $sqlquery = "SELECT - agenda.*, item_property.* - FROM ".$TABLEAGENDA." agenda, - ".$TABLE_ITEMPROPERTY." item_property - WHERE agenda.id = item_property.ref - AND MONTH(agenda.start_date)='".$month."' - AND YEAR(agenda.start_date)='".$year."' - AND item_property.tool='".TOOL_CALENDAR_EVENT."' - AND ( item_property.to_user_id='".api_get_user_id()."' OR item_property.to_group_id='0') - AND item_property.visibility='1' - ORDER BY start_date "; - } - } + $form->addElement('text', 'start_date', get_lang('StartDate')); + $form->addElement('text', 'end_date', get_lang('EndDate')); - $mycourse = api_get_course_info(); - $result = Database::query($sqlquery); + // Repeating the calendar item + if (empty($id)) { + $form->addElement( + 'label', + null, + ' +  '.get_lang('RepeatEvent').' + ' + ); + $form->addElement('html', ''); + } - while ($item = Database::fetch_array($result)) { - $agendaday_string = api_convert_and_format_date($item['start_date'], "%d", date_default_timezone_get()); - $agendaday = intval($agendaday_string); - $time = api_convert_and_format_date($item['start_date'], TIME_NO_SEC_FORMAT); - $URL = api_get_path(WEB_CODE_PATH).'calendar/agenda.php?cidReq='.$mycourse['id']."&day=$agendaday&month=$month&year=$year#$agendaday"; // RH //Patrick Cool: to highlight the relevant agenda item - $items[$agendaday][$item['start_time']] .= ''.$time.' '.$mycourse['official_code'].' '.$item['title'].'
'; - } - // sorting by hour for every day - $agendaitems = array(); - while (list ($agendaday, $tmpitems) = each($items)) { - sort($tmpitems); - while (list ($key, $val) = each($tmpitems)) { - $agendaitems[$agendaday] .= $val; - } + if (isset($agendaItem['all_day'])) { + $checked = null; + if ($agendaItem['all_day']) { + $checked = 'checked'; } - return $agendaitems; + $form->addElement('checkbox', 'all_day', get_lang('AllDay')); } - function display_upcoming_events() - { - - $number_of_items_to_show = (int) api_get_setting('number_of_upcoming_events'); - - //databases of the courses - $TABLEAGENDA = Database :: get_course_table(TABLE_AGENDA); - $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY); - $mycourse = api_get_course_info(); - $myuser = api_get_user_info(); - $session_id = api_get_session_id(); + $form->addElement('html_editor', 'content', get_lang('Description')); + $form->addElement('checkbox', 'add_announcement', get_lang('AddAnnouncement').' ('.get_lang('SendMail').')'); - $course_id = $mycourse['real_id']; - - - $group_memberships = GroupManager :: get_group_ids($mycourse['real_id'], $myuser['user_id']); - // if the user is administrator of that course we show all the agenda items - if (api_is_allowed_to_edit(false, true)) { - //echo "course admin"; - $sqlquery = "SELECT - DISTINCT agenda.*, item_property.* - FROM ".$TABLEAGENDA." agenda, - ".$TABLE_ITEMPROPERTY." item_property - WHERE - agenda.c_id = $course_id AND - item_property.c_id = $course_id AND - agenda.id = item_property.ref - AND item_property.tool='".TOOL_CALENDAR_EVENT."' - AND item_property.visibility='1' - AND agenda.start_date > NOW() - AND session_id = '".$session_id."' - GROUP BY agenda.id - ORDER BY start_date "; - } - // if the user is not an administrator of that course - else { - //echo "GEEN course admin"; - if (is_array($group_memberships) and count($group_memberships) > 0) { - $sqlquery = "SELECT - agenda.*, item_property.* - FROM ".$TABLEAGENDA." agenda, - ".$TABLE_ITEMPROPERTY." item_property - WHERE - agenda.c_id = $course_id AND - item_property.c_id = $course_id AND - agenda.id = item_property.ref - AND item_property.tool='".TOOL_CALENDAR_EVENT."' - AND ( item_property.to_user_id='".$myuser['user_id']."' OR item_property.to_group_id IN (0, ".implode(", ", $group_memberships).") ) - AND item_property.visibility='1' - AND agenda.start_date > NOW() - AND session_id = '".$session_id."' - ORDER BY start_date "; - } else { - $sqlquery = "SELECT - agenda.*, item_property.* - FROM ".$TABLEAGENDA." agenda, - ".$TABLE_ITEMPROPERTY." item_property - WHERE - agenda.c_id = $course_id AND - item_property.c_id = $course_id AND - agenda.id = item_property.ref - AND item_property.tool='".TOOL_CALENDAR_EVENT."' - AND ( item_property.to_user_id='".$myuser['user_id']."' OR item_property.to_group_id='0') - AND item_property.visibility='1' - AND agenda.start_date > NOW() - AND session_id = '".$session_id."' - ORDER BY start_date "; - } - } - $result = Database::query($sqlquery); - $counter = 0; + if ($agendaObj->type == 'course') { + // File attachment + $form->addElement('file', 'user_upload', get_lang('AddAnAttachment')); + $form->addElement('textarea', 'file_comment', get_lang('Comment')); + $form->add_progress_bar(); + } - if (Database::num_rows($result) > 0) { - echo '

'.get_lang('UpcomingEvent').'


'; - while ($item = Database::fetch_array($result, 'ASSOC')) { - if ($counter < $number_of_items_to_show) { - echo api_get_local_time($item['start_date']), ' - ', $item['title'], '
'; - $counter++; - } - } - } + if (isset($_GET['id'])) { + $text = get_lang('ModifyEvent'); + } else { + $text = get_lang('AgendaAdd'); } + $form->addElement('button', 'submit', $text); + return $form->return_form(); +} /** * This function calculates the startdate of the week (monday) @@ -2956,6 +2154,7 @@ function show_add_form($id = '', $type = null) /** * Show the mini calendar of the given month + * @deprecated */ function display_daycalendar($agendaitems, $day, $month, $year, $weekdaynames, $monthName) { @@ -3046,6 +2245,7 @@ function show_add_form($id = '', $type = null) /** * Display the weekly view of the calendar + * @deprecated */ function display_weekcalendar($agendaitems, $month, $year, $weekdaynames, $monthName) { @@ -3138,6 +2338,7 @@ function show_add_form($id = '', $type = null) /** * Show the monthcalender of the given month + * @deprecated */ function get_day_agendaitems($courses_dbs, $month, $year, $day) { @@ -3247,6 +2448,7 @@ function show_add_form($id = '', $type = null) /** * Return agenda items of the week + * @deprecated */ function get_week_agendaitems($courses_dbs, $month, $year, $week = '') { @@ -3322,11 +2524,6 @@ function show_add_form($id = '', $type = null) ORDER BY a.start_date"; } } - //echo "
".$sqlquery."
"; - // $sqlquery = "SELECT * FROM $agendadb WHERE (DAYOFMONTH(day)>='$start_day' AND DAYOFMONTH(day)<='$end_day') - // AND (MONTH(day)>='$start_month' AND MONTH(day)<='$end_month') - // AND (YEAR(day)>='$start_year' AND YEAR(day)<='$end_year')"; - //var_dump($sqlquery); $result = Database::query($sqlquery); while ($item = Database::fetch_array($result)) { $agendaday_string = api_convert_and_format_date($item['start_date'], "%d", date_default_timezone_get()); @@ -4128,11 +3325,10 @@ function show_add_form($id = '', $type = null) $sql = "DELETE FROM $agenda_table_attachment WHERE id = ".$id_attach; $result = Database::query($sql); - $last_id_file = Database::insert_id(); // update item_property api_item_property_update($_course, 'calendar_event_attachment', $id_attach, 'AgendaAttachmentDeleted', api_get_user_id()); if (!empty($result)) { - Display::display_confirmation_message(get_lang("AttachmentFileDeleteSuccess")); + return Display::return_message(get_lang("AttachmentFileDeleteSuccess"), 'confirmation'); } } @@ -4338,6 +3534,7 @@ function show_add_form($id = '', $type = null) * Import an iCal file into the database * @param array Course info * @return boolean True on success, false otherwise + * @deprecated */ function agenda_import_ical($course_info, $file) { @@ -4396,7 +3593,6 @@ function show_add_form($id = '', $type = null) $attendee = $ve->getProperty('attendee'); $course_name = $ve->getProperty('location'); //insert the event in our database - //var_dump($title,$desc,$start_date,$end_date); $id = agenda_add_item($course_info,$title,$desc,$start_date_string,$end_date_string,$_POST['selectedform']); @@ -4490,9 +3686,14 @@ function show_add_form($id = '', $type = null) if ($start_date_string == $date->format('Y-m-d h:i:s')) { $all_day = 'true'; } - - //var_dump($start_date_string, $end_date_string, $all_day); - $id = $agenda_obj->add_event($start_date_string, $end_date_string, $all_day, null, $title, $desc, array('everyone')); + $id = $agenda_obj->add_event( + $start_date_string, + $end_date_string, + $all_day, + $title, + $desc, + array('everyone') + ); $message[] = " $title - ".$start_date_string." - ".$end_date_string; @@ -4653,5 +3854,5 @@ function show_add_form($id = '', $type = null) $form->addElement('file', 'ical_import', get_lang('ICalFileImport')); $form->addRule('ical_import', get_lang('ThisFieldIsRequired'), 'required'); $form->addElement('button', 'ical_submit', get_lang('Import')); - $form->display(); + return $form->return_form(); } diff --git a/main/calendar/agenda.lib.php b/main/calendar/agenda.lib.php index cab9ce254e..c21c5296cd 100644 --- a/main/calendar/agenda.lib.php +++ b/main/calendar/agenda.lib.php @@ -2,12 +2,20 @@ /* For licensing terms, see /license.txt */ /** - * @author: Julio Montoya Implementing a real agenda lib + * Class Agenda + * + * @author: Julio Montoya */ + class Agenda { public $events = array(); - public $type = 'personal'; // personal, admin or course + /** @var string Current type */ + public $type = 'personal'; + public $types = array('personal', 'admin', 'course'); + public $sessionId = 0; + /** @var array */ + public $course; /** * @@ -18,14 +26,15 @@ class Agenda $this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR); $this->tbl_personal_agenda = Database::get_user_personal_table(TABLE_PERSONAL_AGENDA); $this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA); + $this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT); //Setting the course object if we are in a course $this->course = null; - $course_info = api_get_course_info(); - if (!empty($course_info)) { - $this->course = $course_info; + $courseInfo = api_get_course_info(); + if (!empty($courseInfo)) { + $this->course = $courseInfo; } - + $this->sessionId = api_get_session_id(); $this->events = array(); //Event colors @@ -37,131 +46,248 @@ class Agenda } /** - * @param array $course_info + * @param array $courseInfo */ - public function set_course($course_info) + public function set_course($courseInfo) { - $this->course = $course_info; + $this->course = $courseInfo; + } + + /** + * @return array + */ + public function getTypes() + { + return $this->types; } /** - * * Adds an event to the calendar + * @param string $start datetime format: 2012-06-14 09:00:00 + * @param string $end datetime format: 2012-06-14 09:00:00 + * @param string $allDay (true, false) + * @param string $title + * @param string $content + * @param array $usersToSend array('everyone') or a list of user/group ids + * @param bool $addAsAnnouncement event as a *course* announcement + * @param int $parentEventId + * @param array $attachmentArray $_FILES[''] + * @param string $attachmentComment * - * @param string start datetime format: 2012-06-14 09:00:00 - * @param string end datetime format: 2012-06-14 09:00:00 - * @param string all day (true, false) - * @param string view agendaDay, agendaWeek, month @todo seems not to be used - * @param string title - * @param string content - * @param array users to send array('everyone') or a list of user ids - * @param bool add event as a *course* announcement * @return int - * */ public function add_event( $start, $end, - $all_day, - $view, + $allDay, $title, $content, - $users_to_send = array(), - $add_as_announcement = false, - $parentEventId = null + $usersToSend = array(), + $addAsAnnouncement = false, + $parentEventId = null, + $attachmentArray = array(), + $attachmentComment = null ) { $start = api_get_utc_datetime($start); $end = api_get_utc_datetime($end); - $all_day = isset($all_day) && $all_day == 'true' ? 1 : 0; + $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0; - $attributes = array(); $id = null; switch ($this->type) { case 'personal': - $attributes['user'] = api_get_user_id(); - $attributes['title'] = $title; - $attributes['text'] = $content; - $attributes['date'] = $start; - $attributes['enddate'] = $end; - $attributes['all_day'] = $all_day; + $attributes = array( + 'user' => api_get_user_id(), + 'title' => $title, + 'text' => $content, + 'date' => $start, + 'enddate' => $end, + 'all_day' => $allDay + ); $id = Database::insert($this->tbl_personal_agenda, $attributes); break; case 'course': - $attributes['title'] = $title; - $attributes['content'] = $content; - $attributes['start_date'] = $start; - $attributes['end_date'] = $end; - $attributes['all_day'] = $all_day; - $attributes['session_id'] = api_get_session_id(); - $attributes['c_id'] = $this->course['real_id']; + $attributes = array( + 'title' => $title, + 'content' => $content, + 'start_date' => $start, + 'end_date' => $end, + 'all_day' => $allDay, + 'session_id' => api_get_session_id(), + 'c_id' => $this->course['real_id'] + ); if (!empty($parentEventId)) { $attributes['parent_event_id'] = $parentEventId; } - //simple course event + // Simple course event. $id = Database::insert($this->tbl_course_agenda, $attributes); if ($id) { $group_id = api_get_group_id(); - if ((!is_null($users_to_send)) or (!empty($group_id))) { - $send_to = self::separate_users_groups($users_to_send); - if (isset($send_to['everyone']) && $send_to['everyone']) { - api_item_property_update($this->course, TOOL_CALENDAR_EVENT, $id, "AgendaAdded", api_get_user_id(), $group_id, '', $start, $end); + if (!empty($usersToSend)) { + $sendTo = $this->parseSendToArray($usersToSend); + + if ($sendTo['everyone']) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "AgendaAdded", + api_get_user_id(), + $group_id, + '', + $start, + $end + ); + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "visible", + api_get_user_id(), + $group_id, + '', + $start, + $end + ); } else { - // storing the selected groups - if (isset($send_to['groups']) && is_array($send_to['groups'])) { - foreach ($send_to['groups'] as $group) { - api_item_property_update($this->course, TOOL_CALENDAR_EVENT, $id, "AgendaAdded", api_get_user_id(), $group, 0, $start, $end); + // Storing the selected groups + if (!empty($sendTo['groups'])) { + foreach ($sendTo['groups'] as $group) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "AgendaAdded", + api_get_user_id(), + $group, + 0, + $start, + $end + ); + + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "visible", + api_get_user_id(), + $group, + 0, + $start, + $end + ); } } // storing the selected users - if (isset($send_to['groups']) && is_array($send_to['users'])) { - foreach ($send_to['users'] as $to_user_id) { - api_item_property_update($this->course, TOOL_CALENDAR_EVENT, $id, "AgendaAdded", api_get_user_id(), $group_id, $to_user_id, $start, $end); + if (!empty($sendTo['users'])) { + foreach ($sendTo['users'] as $userId) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "AgendaAdded", + api_get_user_id(), + $group_id, + $userId, + $start, + $end + ); + + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "visible", + api_get_user_id(), + $group_id, + $userId, + $start, + $end + ); } } } } - if (isset($add_as_announcement) && !empty($add_as_announcement)) { - self::store_agenda_item_as_announcement($id, $users_to_send); + // Add announcement. + if ($addAsAnnouncement) { + $this->store_agenda_item_as_announcement($id, $usersToSend); + } + + // Add attachment. + if (isset($attachmentArray) && !empty($attachmentArray)) { + $this->addAttachment( + $id, + $attachmentArray, + $attachmentComment, + $this->course + ); } } break; case 'admin': if (api_is_platform_admin()) { - $attributes['title'] = $title; - $attributes['content'] = $content; - $attributes['start_date'] = $start; - $attributes['end_date'] = $end; - $attributes['all_day'] = $all_day; - $attributes['access_url_id'] = api_get_current_access_url_id(); + $attributes = array( + 'title' => $title, + 'content' => $content, + 'start_date' => $start, + 'end_date' => $end, + 'all_day' => $allDay, + 'access_url_id' => api_get_current_access_url_id() + ); + $id = Database::insert($this->tbl_global_agenda, $attributes); } break; } + return $id; } /** * @param int $eventId - * @param string $type - * @param string $end date time - * @param array $sentTo - * @return bool + * @param int $courseId + * + * @return array */ + public function getRepeatedInfoByEvent($eventId, $courseId) + { + $repeatTable = Database::get_course_table(TABLE_AGENDA_REPEAT); + $eventId = intval($eventId); + $courseId = intval($courseId); + $sql = "SELECT * FROM $repeatTable + WHERE c_id = $courseId AND cal_id = $eventId"; + $res = Database::query($sql); + $repeatInfo = array(); + if (Database::num_rows($res) > 0) { + $repeatInfo = Database::fetch_array($res, 'ASSOC'); + } + + return $repeatInfo; + } + + /** + * @param int $eventId + * @param string $type + * @param string $end date time + * @param array $sentTo + * + * @return bool + */ public function addRepeatedItem($eventId, $type, $end, $sentTo = array()) { $t_agenda = Database::get_course_table(TABLE_AGENDA); $t_agenda_r = Database::get_course_table(TABLE_AGENDA_REPEAT); $course_id = $this->course['real_id']; + $eventId = intval($eventId); - $sql = 'SELECT title, content, start_date as sd, end_date as ed - FROM '.$t_agenda.' - WHERE c_id = '.$course_id.' AND id ="'.intval($eventId).'" '; + $sql = "SELECT title, content, start_date as sd, end_date as ed, all_day + FROM $t_agenda + WHERE c_id = $course_id AND id = $eventId"; $res = Database::query($sql); if (Database::num_rows($res) !== 1) { @@ -169,28 +295,29 @@ class Agenda } $row = Database::fetch_array($res); - $orig_start = api_strtotime(api_get_local_time($row['sd'])); - $orig_end = api_strtotime(api_get_local_time($row['ed'])); + $orig_start = api_strtotime($row['sd']); + $orig_end = api_strtotime($row['ed']); $diff = $orig_end - $orig_start; $orig_title = $row['title']; $orig_content = $row['content']; + $allDay = $row['all_day']; $now = time(); $type = Database::escape_string($type); - $end = intval($end); + $end = api_strtotime($end); if (1 <= $end && $end <= 500) { - //we assume that, with this type of value, the user actually gives a count of repetitions + // We assume that, with this type of value, the user actually gives a count of repetitions //and that he wants us to calculate the end date with that (particularly in case of imports from ical) switch ($type) { case 'daily': $end = $orig_start + (86400 * $end); break; case 'weekly': - $end = self::add_week($orig_start, $end); + $end = $this->addWeek($orig_start, $end); break; case 'monthlyByDate': - $end = self::add_month($orig_start, $end); + $end = $this->addMonth($orig_start, $end); break; case 'monthlyByDay': //TODO @@ -199,27 +326,28 @@ class Agenda //TODO break; case 'yearly': - $end = self::add_year($orig_start, $end); + $end = $this->addYear($orig_start, $end); break; } } $typeList = array('daily', 'weekly', 'monthlyByDate', 'monthlyByDay', 'monthlyByDayR', 'yearly'); + if ($end > $now && in_array($type, $typeList)) { $sql = "INSERT INTO $t_agenda_r (c_id, cal_id, cal_type, cal_end) VALUES ($course_id, '$eventId', '$type', '$end')"; Database::query($sql); switch ($type) { + // @todo improve loop. case 'daily': - for ($i = $orig_start + 86400; ($i <= $end); $i += 86400) { + for ($i = $orig_start + 86400; $i <= $end; $i += 86400) { $start = date('Y-m-d H:i:s', $i); - $end = date('Y-m-d H:i:s', $i + $diff); - self::add_event( + $repeatEnd = date('Y-m-d H:i:s', $i + $diff); + $this->add_event( $start, - $end, - false, - null, + $repeatEnd, + $allDay, $orig_title, $orig_content, $sentTo, @@ -229,15 +357,13 @@ class Agenda } break; case 'weekly': - for ($i = $orig_start + 604800; ($i <= $end); $i += 604800) { - //agenda_add_item($this->course, $orig_title, $orig_content, date('Y-m-d H:i:s', $i), date('Y-m-d H:i:s', $i + $diff), $orig_dest, $orig_id, $file_comment); + for ($i = $orig_start + 604800; $i <= $end; $i += 604800) { $start = date('Y-m-d H:i:s', $i); - $end = date('Y-m-d H:i:s', $i + $diff); - self::add_event( + $repeatEnd = date('Y-m-d H:i:s', $i + $diff); + $this->add_event( $start, - $end, - false, - null, + $repeatEnd, + $allDay, $orig_title, $orig_content, $sentTo, @@ -247,24 +373,21 @@ class Agenda } break; case 'monthlyByDate': - $next_start = add_month($orig_start); + $next_start = $this->addMonth($orig_start); while ($next_start <= $end) { $start = date('Y-m-d H:i:s', $next_start); - $end = date('Y-m-d H:i:s', $next_start + $diff); - self::add_event( + $repeatEnd = date('Y-m-d H:i:s', $next_start + $diff); + $this->add_event( $start, - $end, - false, - null, + $repeatEnd, + $allDay, $orig_title, $orig_content, $sentTo, false, $eventId ); - - //agenda_add_item($this->course, $orig_title, $orig_content, date('Y-m-d H:i:s', $next_start), date('Y-m-d H:i:s', $next_start + $diff), $orig_dest, $orig_id, $file_comment); - $next_start = self::add_month($next_start); + $next_start = $this->addMonth($next_start); } break; case 'monthlyByDay': @@ -274,23 +397,21 @@ class Agenda //not yet implemented break; case 'yearly': - $next_start = add_year($orig_start); + $next_start = $this->addYear($orig_start); while ($next_start <= $end) { $start = date('Y-m-d H:i:s', $next_start); - $end = date('Y-m-d H:i:s', $next_start + $diff); - self::add_event( + $repeatEnd = date('Y-m-d H:i:s', $next_start + $diff); + $this->add_event( $start, - $end, - false, - null, + $repeatEnd, + $allDay, $orig_title, $orig_content, $sentTo, false, $eventId ); - //agenda_add_item($this->course, $orig_title, $orig_content, date('Y-m-d H:i:s', $next_start), date('Y-m-d H:i:s', $next_start + $diff), $orig_dest, $orig_id, $file_comment); - $next_start = self::add_year($next_start); + $next_start = $this->addYear($next_start); } break; } @@ -300,10 +421,10 @@ class Agenda /** * @param int $item_id - * @param array $sent_to + * @param array $sentTo * @return int */ - public function store_agenda_item_as_announcement($item_id, $sent_to = array()) + public function store_agenda_item_as_announcement($item_id, $sentTo = array()) { $table_agenda = Database::get_course_table(TABLE_AGENDA); $course_id = api_get_course_int_id(); @@ -321,11 +442,11 @@ class Agenda if (Database::num_rows($res) > 0) { $row = Database::fetch_array($res, 'ASSOC'); // Sending announcement - if (!empty($sent_to)) { + if (!empty($sentTo)) { $id = AnnouncementManager::add_announcement( $row['title'], $row['content'], - $sent_to, + $sentTo, null, null, $row['end_date'] @@ -340,24 +461,33 @@ class Agenda /** * Edits an event * - * @param int event id - * @param string start datetime format: 2012-06-14 09:00:00 - * @param string end datetime format: 2012-06-14 09:00:00 - * @param int event is all day? 1|0 - * @param string view - * @param string event title - * @param string event content + * @param int $id id + * @param string $start datetime format: 2012-06-14 09:00:00 + * @param string $end datetime format: 2012-06-14 09:00:00 + * @param int $allDay is all day 'true' or 'false' + * @param string $title + * @param string $content + * @param array $usersToSend + * @param int $editRepeatType + * @param array $attachmentArray + * @param string $attachmentComment + * + * @return bool */ - public function edit_event($id, $start, $end, $all_day, $view, $title, $content) - { + public function edit_event( + $id, + $start, + $end, + $allDay, + $title, + $content, + $usersToSend = array(), + $editRepeatType = 1, + $attachmentArray = array(), + $attachmentComment = null + ) { $start = api_get_utc_datetime($start); - - if ($all_day == '0') { - $end = api_get_utc_datetime($end); - } - $all_day = isset($all_day) && $all_day == '1' ? 1 : 0; - - $attributes = array(); + $allDay = isset($allDay) && $allDay == 'true' ? 1 : 0; switch ($this->type) { case 'personal': @@ -365,56 +495,299 @@ class Agenda if ($eventInfo['user'] != api_get_user_id()) { break; } - $attributes['title'] = $title; - $attributes['text'] = $content; - $attributes['date'] = $start; - $attributes['enddate'] = $end; - Database::update($this->tbl_personal_agenda, $attributes, array('id = ?' => $id)); + $attributes = array( + 'title' => $title, + 'text' => $content, + 'date' => $start, + 'enddate' => $end, + 'all_day' => $allDay + ); + Database::update( + $this->tbl_personal_agenda, + $attributes, + array('id = ?' => $id) + ); break; case 'course': + $eventInfo = $this->get_event($id); + + if (empty($eventInfo)) { + return false; + } + + $group_id = api_get_group_id(); $course_id = api_get_course_int_id(); - if (!empty($course_id) && api_is_allowed_to_edit(null, true)) { - $attributes['title'] = $title; - $attributes['content'] = $content; - $attributes['start_date'] = $start; - $attributes['end_date'] = $end; - $attributes['all_day'] = $all_day; - Database::update($this->tbl_course_agenda, $attributes, array('id = ? AND c_id = ?' => array($id, $course_id))); + + if (empty($course_id)) { + return false; + } + + if (api_is_allowed_to_edit(null, true)) { + + $attributes = array( + 'title' => $title, + 'content' => $content, + 'start_date' => $start, + 'end_date' => $end, + 'all_day' => $allDay + ); + + Database::update( + $this->tbl_course_agenda, + $attributes, + array( + 'id = ? AND c_id = ? AND session_id = ? ' => array($id, $course_id, api_get_session_id()) + ) + ); + + if (!empty($usersToSend)) { + $sendTo = $this->parseSendToArray($usersToSend); + + $usersToDelete = array_diff($eventInfo['send_to']['users'], $sendTo['users']); + $usersToAdd = array_diff($sendTo['users'], $eventInfo['send_to']['users']); + + $groupsToDelete = array_diff($eventInfo['send_to']['groups'], $sendTo['groups']); + $groupToAdd = array_diff($sendTo['groups'], $eventInfo['send_to']['groups']); + + if ($sendTo['everyone']) { + // Delete all: + if (!empty($eventInfo['send_to']['groups']) && + isset($eventInfo['send_to']['groups']) + ) { + foreach ($eventInfo['send_to']['groups'] as $group) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "delete", + api_get_user_id(), + $group, + 0, + $start, + $end, + $this->sessionId + ); + } + } + + // storing the selected users + if (!empty($eventInfo['send_to']['users']) && + isset($eventInfo['send_to']['users']) + ) { + foreach ($eventInfo['send_to']['users'] as $userId) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "delete", + api_get_user_id(), + $group_id, + $userId, + $start, + $end, + $this->sessionId + ); + } + } + + // Add to everyone only. + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "visible", + api_get_user_id(), + $group_id, + '', + $start, + $end, + $this->sessionId + ); + } else { + // Groups + if (!empty($groupToAdd)) { + foreach ($groupToAdd as $group) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "visible", + api_get_user_id(), + $group, + 0, + $start, + $end, + $this->sessionId + ); + } + } + + if (!empty($groupsToDelete)) { + foreach ($groupsToDelete as $group) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "delete", + api_get_user_id(), + $group, + 0, + $start, + $end, + $this->sessionId + ); + } + } + + // Users. + if (!empty($usersToAdd)) { + foreach ($usersToAdd as $userId) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "visible", + api_get_user_id(), + $group_id, + $userId, + $start, + $end, + $this->sessionId + ); + } + } + + if (!empty($usersToDelete)) { + foreach ($usersToDelete as $userId) { + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + "delete", + api_get_user_id(), + $group_id, + $userId, + $start, + $end, + $this->sessionId + ); + } + } + } + } + + // Add announcement. + /*if (isset($addAsAnnouncement) && !empty($addAsAnnouncement)) { + $this->store_agenda_item_as_announcement($id); + }*/ + + // Repeat + //$editRepeatType = null; + + // Add attachment. + if (isset($attachmentArray) && !empty($attachmentArray)) { + $this->updateAttachment( + $id, + $attachmentArray, + $attachmentComment, + $this->course + ); + } } break; case 'admin': + case 'platform': if (api_is_platform_admin()) { - $attributes['title'] = $title; - $attributes['content'] = $content; - $attributes['start_date'] = $start; - $attributes['end_date'] = $end; - Database::update($this->tbl_global_agenda, $attributes, array('id = ?' => $id)); + $attributes = array( + 'title' => $title, + 'content' => $content, + 'start_date' => $start, + 'end_date' => $end, + 'all_day' => $allDay + ); + Database::update( + $this->tbl_global_agenda, + $attributes, + array('id = ?' => $id) + ); } break; } } /** - * @param $id + * @param int $id + * @param bool $deleteAllItemsFromSerie */ - public function delete_event($id) + public function delete_event($id, $deleteAllItemsFromSerie = false) { switch ($this->type) { case 'personal': $eventInfo = $this->get_event($id); if ($eventInfo['user'] == api_get_user_id()) { - Database::delete($this->tbl_personal_agenda, array('id = ?' => $id)); + Database::delete( + $this->tbl_personal_agenda, + array('id = ?' => $id) + ); } break; case 'course': $course_id = api_get_course_int_id(); if (!empty($course_id) && api_is_allowed_to_edit(null, true)) { - Database::delete($this->tbl_course_agenda, array('id = ? AND c_id = ?' => array($id, $course_id))); + // Delete + if ($deleteAllItemsFromSerie) { + $eventInfo = $this->get_event($id); + /* This is one of the children. + Getting siblings and delete 'Em all + the father! */ + if (isset($eventInfo['parent_event_id']) && !empty($eventInfo['parent_event_id'])) { + // Removing items. + $events = $this->getAllRepeatEvents($eventInfo['parent_event_id']); + if (!empty($events)) { + foreach ($events as $event) { + $this->delete_event($event['id']); + } + } + // Removing parent. + $this->delete_event($eventInfo['parent_event_id']); + } else { + // This is the father looking for the children. + $events = $this->getAllRepeatEvents($id); + if (!empty($events)) { + foreach ($events as $event) { + $this->delete_event($event['id']); + } + } + } + } + + + // Removing from events. + Database::delete( + $this->tbl_course_agenda, + array('id = ? AND c_id = ?' => array($id, $course_id)) + ); + + api_item_property_update( + $this->course, + TOOL_CALENDAR_EVENT, + $id, + 'delete', + api_get_user_id() + ); + + // Removing from series. + Database::delete( + $this->table_repeat, + array('cal_id = ? AND c_id = ?' => array($id, $course_id)) + ); } break; case 'admin': if (api_is_platform_admin()) { - Database::delete($this->tbl_global_agenda, array('id = ?' => $id)); + Database::delete( + $this->tbl_global_agenda, + array('id = ?' => $id) + ); } break; } @@ -438,8 +811,15 @@ class Agenda break; case 'course': $session_id = api_get_session_id(); - $course_info = api_get_course_info_by_id($course_id); - $this->get_course_events($start, $end, $course_info, $group_id, $session_id, $user_id); + $courseInfo = api_get_course_info_by_id($course_id); + $this->get_course_events( + $start, + $end, + $courseInfo, + $group_id, + $session_id, + $user_id + ); break; case 'personal': default: @@ -463,8 +843,8 @@ class Agenda $my_session_id = $session_item['session_id']; if (!empty($my_courses)) { foreach ($my_courses as $course_item) { - $course_info = api_get_course_info($course_item['code']); - $this->get_course_events($start, $end, $course_info, 0, $my_session_id); + $courseInfo = api_get_course_info($course_item['code']); + $this->get_course_events($start, $end, $courseInfo, 0, $my_session_id); } } } @@ -547,25 +927,25 @@ class Agenda $event = $this->get_event($id); - $all_day = 0; + $allDay = 0; if ($day_delta == 0 && $minute_delta == 0) { - $all_day = 1; + $allDay = 1; } if (!empty($event)) { switch ($this->type) { case 'personal': - $sql = "UPDATE $this->tbl_personal_agenda SET all_day = $all_day, date = DATE_ADD(date, INTERVAL $delta MINUTE), enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE) + $sql = "UPDATE $this->tbl_personal_agenda SET all_day = $allDay, date = DATE_ADD(date, INTERVAL $delta MINUTE), enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE) WHERE id=".intval($id); $result = Database::query($sql); break; case 'course': - $sql = "UPDATE $this->tbl_course_agenda SET all_day = $all_day, start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE), end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE) + $sql = "UPDATE $this->tbl_course_agenda SET all_day = $allDay, start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE), end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE) WHERE c_id = ".$this->course['real_id']." AND id=".intval($id); $result = Database::query($sql); break; case 'admin': - $sql = "UPDATE $this->tbl_global_agenda SET all_day = $all_day, start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE), end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE) + $sql = "UPDATE $this->tbl_global_agenda SET all_day = $allDay, start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE), end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE) WHERE id=".intval($id); $result = Database::query($sql); break; @@ -587,28 +967,51 @@ class Agenda $event = null; switch ($this->type) { case 'personal': - $sql = " SELECT * FROM ".$this->tbl_personal_agenda." WHERE id = $id AND user = ".api_get_user_id(); + $sql = "SELECT * FROM ".$this->tbl_personal_agenda." + WHERE id = $id AND user = ".api_get_user_id(); $result = Database::query($sql); if (Database::num_rows($result)) { $event = Database::fetch_array($result, 'ASSOC'); $event['description'] = $event['text']; + $event['content'] = $event['text']; $event['start_date'] = $event['date']; $event['end_date'] = $event['enddate']; } break; case 'course': if (!empty($this->course['real_id'])) { - $sql = " SELECT * FROM ".$this->tbl_course_agenda." WHERE c_id = ".$this->course['real_id']." AND id = ".$id; + $sql = "SELECT * FROM ".$this->tbl_course_agenda." + WHERE c_id = ".$this->course['real_id']." AND id = ".$id; $result = Database::query($sql); if (Database::num_rows($result)) { $event = Database::fetch_array($result, 'ASSOC'); $event['description'] = $event['content']; + + // Getting send to array + $event['send_to'] = $this->getUsersAndGroupSubscribedToEvent( + $id, + $this->course['real_id'], + $this->sessionId + ); + + // Getting repeat info + $event['repeat_info'] = $this->getRepeatedInfoByEvent( + $id, + $this->course['real_id'] + ); + + if (!empty($event['parent_event_id'])) { + $event['parent_info'] = $this->get_event($event['parent_event_id']); + } + + $event['attachment'] = $this->getAttachment($id, $this->course); } } break; case 'admin': case 'platform': - $sql = " SELECT * FROM ".$this->tbl_global_agenda." WHERE id=".$id; + $sql = "SELECT * FROM ".$this->tbl_global_agenda." + WHERE id = ".$id; $result = Database::query($sql); if (Database::num_rows($result)) { $event = Database::fetch_array($result, 'ASSOC'); @@ -649,13 +1052,19 @@ class Agenda if (!empty($row['date']) && $row['date'] != '0000-00-00 00:00:00') { $event['start'] = $this->format_event_date($row['date']); + $event['start_date_localtime'] = api_get_local_time($row['date']); } if (!empty($row['enddate']) && $row['enddate'] != '0000-00-00 00:00:00') { $event['end'] = $this->format_event_date($row['enddate']); + $event['end_date_localtime'] = api_get_local_time($row['enddate']); } $event['description'] = $row['text']; $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0; + + $event['parent_event_id'] = 0; + $event['has_children'] = 0; + $my_events[] = $event; $this->events[] = $event; } @@ -663,28 +1072,89 @@ class Agenda return $my_events; } + /** + * Get user/group list per event. + * + * @param int $eventId + * @param int $courseId + * @paraù int $sessionId + * + * @return array + */ + public function getUsersAndGroupSubscribedToEvent($eventId, $courseId, $sessionId) + { + $eventId = intval($eventId); + $courseId = intval($courseId); + $sessionId = intval($sessionId); + + $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA); + $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY); + + // Get sent_tos + $sql = "SELECT DISTINCT to_user_id, to_group_id + FROM $tbl_property ip + INNER JOIN $tlb_course_agenda agenda + ON (ip.ref = agenda.id AND ip.c_id = agenda.c_id) + WHERE + ip.tool = '".TOOL_CALENDAR_EVENT."' AND + ref = $eventId AND + ip.visibility = '1' AND + ip.c_id = $courseId AND + ip.id_session = $sessionId + "; + + $result = Database::query($sql); + $users = array(); + $groups = array(); + $everyone = false; + + while ($row = Database::fetch_array($result, 'ASSOC')) { + if (!empty($row['to_group_id'])) { + $groups[] = $row['to_group_id']; + } + if (!empty($row['to_user_id'])) { + $users[] = $row['to_user_id']; + } + + if (empty($groups) && empty($users)) { + if ($row['to_group_id'] == 0) { + $everyone = true; + } + } + } + + return array( + 'everyone' => $everyone, + 'users' => $users, + 'groups' => $groups + ); + } + /** * @param int $start * @param int $end - * @param $course_info + * @param array $courseInfo * @param int $group_id * @param int $session_id * @param int $user_id * @return array */ - public function get_course_events($start, $end, $course_info, $group_id = 0, $session_id = 0, $user_id = 0) + public function get_course_events($start, $end, $courseInfo, $group_id = 0, $session_id = 0, $user_id = 0) { - $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)): null; - $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)): null; + $start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null; + $end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null; - $course_id = $course_info['real_id']; + $course_id = $courseInfo['real_id']; + if (empty($course_id)) { + return array(); + } $user_id = intval($user_id); - $group_list = GroupManager::get_group_list(null, $course_info['code']); + $groupList = GroupManager::get_group_list(null, $courseInfo['code']); $group_name_list = array(); - if (!empty($group_list)) { - foreach ($group_list as $group) { + if (!empty($groupList)) { + foreach ($groupList as $group) { $group_name_list[$group['id']] = $group['name']; } } @@ -721,15 +1191,15 @@ class Agenda } $sql = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref, to_user_id - FROM ".$tlb_course_agenda." agenda, ".$tbl_property." ip - WHERE agenda.id = ip.ref AND - ip.tool ='".TOOL_CALENDAR_EVENT."' AND - $where_condition AND - ip.visibility = '1' AND - agenda.c_id = $course_id AND - ip.c_id = $course_id - - GROUP BY id"; + FROM $tlb_course_agenda agenda INNER JOIN $tbl_property ip + ON (agenda.id = ip.ref AND agenda.c_id = ip.c_id) + WHERE + ip.tool ='".TOOL_CALENDAR_EVENT."' AND + $where_condition AND + ip.visibility = '1' AND + agenda.c_id = $course_id AND + ip.c_id = $course_id + "; } else { $visibilityCondition = "ip.visibility='1' AND"; if (api_is_allowed_to_edit()) { @@ -743,50 +1213,37 @@ class Agenda $where_condition = "( ip.to_user_id=$user_id OR ip.to_group_id='0') AND "; } $sql = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref, to_user_id - FROM ".$tlb_course_agenda." agenda, ".$tbl_property." ip - WHERE agenda.id = ip.ref AND - ip.tool='".TOOL_CALENDAR_EVENT."' AND - $where_condition - $visibilityCondition - agenda.c_id = $course_id AND - ip.c_id = $course_id AND - agenda.session_id = $session_id AND - ip.id_session = $session_id + FROM $tlb_course_agenda agenda INNER JOIN $tbl_property ip + ON (agenda.id = ip.ref AND agenda.c_id = ip.c_id) + WHERE + ip.tool='".TOOL_CALENDAR_EVENT."' AND + $where_condition + $visibilityCondition + agenda.c_id = $course_id AND + ip.c_id = $course_id AND + agenda.session_id = $session_id AND + ip.id_session = $session_id "; } + $dateCondition = null; if (!empty($start) && !empty($end)) { - $dateCondition = "AND ( + $dateCondition .= "AND ( (agenda.start_date >= '".$start."' OR agenda.start_date IS NULL) AND (agenda.end_date <= '".$end."' OR agenda.end_date IS NULL) )"; } + $sql .= $dateCondition; + $result = Database::query($sql); if (Database::num_rows($result)) { $events_added = array(); while ($row = Database::fetch_array($result, 'ASSOC')) { - // to gather sent_tos - $sql = "SELECT to_user_id, to_group_id - FROM ".$tbl_property." ip INNER JOIN ".$tlb_course_agenda." agenda - ON ip.ref = agenda.id - WHERE ip.tool = '".TOOL_CALENDAR_EVENT."' AND - ref = {$row['ref']} AND - ip.visibility = '1' AND - ip.c_id = $course_id - $dateCondition"; - $sent_to_result = Database::query($sql); - $user_to_array = array(); - $group_to_array = array(); - while ($row_send_to = Database::fetch_array($sent_to_result, 'ASSOC')) { - if (!empty($row_send_to['to_group_id'])) { - $group_to_array[] = $row_send_to['to_group_id']; - } - if (!empty($row_send_to['to_user_id'])) { - $user_to_array[] = $row_send_to['to_user_id']; - } - } - + $eventId = $row['ref']; + $items = $this->getUsersAndGroupSubscribedToEvent($eventId, $course_id, $this->sessionId); + $group_to_array = $items['groups']; + $user_to_array = $items['users']; $event = array(); $event['id'] = 'course_'.$row['id']; @@ -796,14 +1253,13 @@ class Agenda } $events_added[] = $row['id']; - $attachment = get_attachment($row['id'], $course_id); - $has_attachment = ''; + $attachment = $this->getAttachment($row['id'], $courseInfo); if (!empty($attachment)) { $has_attachment = Display::return_icon('attachment.gif', get_lang('Attachment')); $user_filename = $attachment['filename']; - $full_file_name = 'download.php?file='.$attachment['path'].'&course_id='.$course_id; - $event['attachment'] = $has_attachment.Display::url($user_filename, $full_file_name); + $url = api_get_path(WEB_CODE_PATH).'calendar/download.php?file='.$attachment['path'].'&course_id='.$course_id.'&'.api_get_cidreq(); + $event['attachment'] = $has_attachment.Display::url($user_filename, $url); } else { $event['attachment'] = ''; } @@ -811,7 +1267,6 @@ class Agenda $event['title'] = $row['title']; $event['className'] = 'course'; $event['allDay'] = 'false'; - $event['course_id'] = $course_id; $event['borderColor'] = $event['backgroundColor'] = $this->event_course_color; @@ -831,9 +1286,11 @@ class Agenda if (!empty($row['start_date']) && $row['start_date'] != '0000-00-00 00:00:00') { $event['start'] = $this->format_event_date($row['start_date']); + $event['start_date_localtime'] = api_get_local_time($row['start_date']); } if (!empty($row['end_date']) && $row['end_date'] != '0000-00-00 00:00:00') { $event['end'] = $this->format_event_date($row['end_date']); + $event['end_date_localtime'] = api_get_local_time($row['end_date']); } $event['sent_to'] = ''; @@ -881,6 +1338,8 @@ class Agenda $event['visibility'] = $row['visibility']; $event['real_id'] = $row['id']; $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0; + $event['parent_event_id'] = $row['parent_event_id']; + $event['has_children'] = $this->hasChildren($row['id'], $course_id) ? 1 : 0; $this->events[] = $event; } @@ -904,7 +1363,7 @@ class Agenda $access_url_id = api_get_current_access_url_id(); $sql = "SELECT * FROM ".$this->tbl_global_agenda." - WHERE start_date >= '".$start."' AND end_date <= '".$end."' AND access_url_id = $access_url_id "; + WHERE start_date >= '".$start."' AND end_date <= '".$end."' AND access_url_id = $access_url_id "; $result = Database::query($sql); $my_events = array(); @@ -917,7 +1376,6 @@ class Agenda $event['allDay'] = 'false'; $event['borderColor'] = $event['backgroundColor'] = $this->event_platform_color; $event['editable'] = false; - $event['type'] = 'admin'; if (api_is_platform_admin() && $this->type == 'admin') { @@ -926,14 +1384,19 @@ class Agenda if (!empty($row['start_date']) && $row['start_date'] != '0000-00-00 00:00:00') { $event['start'] = $this->format_event_date($row['start_date']); + $event['start_date_localtime'] = api_get_local_time($row['start_date']); } if (!empty($row['end_date']) && $row['end_date'] != '0000-00-00 00:00:00') { $event['end'] = $this->format_event_date($row['end_date']); + $event['end_date_localtime'] = api_get_local_time($row['end_date']); } $event['description'] = $row['content']; $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0; + $event['parent_event_id'] = 0; + $event['has_children'] = 0; + $my_events[] = $event; $this->events[] = $event; } @@ -960,8 +1423,6 @@ class Agenda public static function construct_not_selected_select_form($group_list = null, $user_list = null, $to_already_selected = array()) { $html = '' + + '
' + + '
' + + '' + + '' + + '
' + + ' ' + + '' + + '' + + '' + + ''; + + //custom options + if (typeof options !== 'object' || options === null) + options = {}; + + this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) || $(this.parentEl); + this.container = $(DRPTemplate).appendTo(this.parentEl); + + this.setOptions(options, cb); + + //apply CSS classes and labels to buttons + var c = this.container; + $.each(this.buttonClasses, function (idx, val) { + c.find('button').addClass(val); + }); + this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel); + this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel); + if (this.applyClass.length) + this.container.find('.applyBtn').addClass(this.applyClass); + if (this.cancelClass.length) + this.container.find('.cancelBtn').addClass(this.cancelClass); + this.container.find('.applyBtn').html(this.locale.applyLabel); + this.container.find('.cancelBtn').html(this.locale.cancelLabel); + + //event listeners + + this.container.find('.calendar') + .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this)) + .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this)) + .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this)) + .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this)) + .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this)) + .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this)) + .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this)) + .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this)); + + this.container.find('.ranges') + .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) + .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this)) + .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this)) + .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this)) + .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this)) + .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this)); + + if (this.element.is('input')) { + this.element.on({ + 'click.daterangepicker': $.proxy(this.show, this), + 'focus.daterangepicker': $.proxy(this.show, this), + 'keyup.daterangepicker': $.proxy(this.updateFromControl, this) + }); + } else { + this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); + } + + }; + + DateRangePicker.prototype = { + + constructor: DateRangePicker, + + setOptions: function(options, callback) { + + this.startDate = moment().startOf('day'); + this.endDate = moment().endOf('day'); + this.minDate = false; + this.maxDate = false; + this.dateLimit = false; + + this.showDropdowns = false; + this.showWeekNumbers = false; + this.timePicker = false; + this.timePickerIncrement = 30; + this.timePicker12Hour = true; + this.singleDatePicker = false; + this.ranges = {}; + + this.opens = 'right'; + if (this.element.hasClass('pull-right')) + this.opens = 'left'; + + this.buttonClasses = ['btn', 'btn-small']; + this.applyClass = 'btn-success'; + this.cancelClass = 'btn-default'; + + this.format = 'MM/DD/YYYY'; + this.separator = ' - '; + + this.locale = { + applyLabel: 'Apply', + cancelLabel: 'Cancel', + fromLabel: 'From', + toLabel: 'To', + weekLabel: 'W', + customRangeLabel: 'Custom Range', + daysOfWeek: moment()._lang._weekdaysMin.slice(), + monthNames: moment()._lang._monthsShort.slice(), + firstDay: 0 + }; + + this.cb = function () { }; + + if (typeof options.format === 'string') + this.format = options.format; + + if (typeof options.separator === 'string') + this.separator = options.separator; + + if (typeof options.startDate === 'string') + this.startDate = moment(options.startDate, this.format); + + if (typeof options.endDate === 'string') + this.endDate = moment(options.endDate, this.format); + + if (typeof options.minDate === 'string') + this.minDate = moment(options.minDate, this.format); + + if (typeof options.maxDate === 'string') + this.maxDate = moment(options.maxDate, this.format); + + if (typeof options.startDate === 'object') + this.startDate = moment(options.startDate); + + if (typeof options.endDate === 'object') + this.endDate = moment(options.endDate); + + if (typeof options.minDate === 'object') + this.minDate = moment(options.minDate); + + if (typeof options.maxDate === 'object') + this.maxDate = moment(options.maxDate); + + if (typeof options.applyClass === 'string') + this.applyClass = options.applyClass; + + if (typeof options.cancelClass === 'string') + this.cancelClass = options.cancelClass; + + if (typeof options.dateLimit === 'object') + this.dateLimit = options.dateLimit; + + // update day names order to firstDay + if (typeof options.locale === 'object') { + + if (typeof options.locale.daysOfWeek === 'object') { + // Create a copy of daysOfWeek to avoid modification of original + // options object for reusability in multiple daterangepicker instances + this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); + } + + if (typeof options.locale.monthNames === 'object') { + this.locale.monthNames = options.locale.monthNames.slice(); + } + + if (typeof options.locale.firstDay === 'number') { + this.locale.firstDay = options.locale.firstDay; + var iterator = options.locale.firstDay; + while (iterator > 0) { + this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); + iterator--; + } + } + + if (typeof options.locale.applyLabel === 'string') { + this.locale.applyLabel = options.locale.applyLabel; + } + + if (typeof options.locale.cancelLabel === 'string') { + this.locale.cancelLabel = options.locale.cancelLabel; + } + + if (typeof options.locale.fromLabel === 'string') { + this.locale.fromLabel = options.locale.fromLabel; + } + + if (typeof options.locale.toLabel === 'string') { + this.locale.toLabel = options.locale.toLabel; + } + + if (typeof options.locale.weekLabel === 'string') { + this.locale.weekLabel = options.locale.weekLabel; + } + + if (typeof options.locale.customRangeLabel === 'string') { + this.locale.customRangeLabel = options.locale.customRangeLabel; + } + } + + if (typeof options.opens === 'string') + this.opens = options.opens; + + if (typeof options.showWeekNumbers === 'boolean') { + this.showWeekNumbers = options.showWeekNumbers; + } + + if (typeof options.buttonClasses === 'string') { + this.buttonClasses = [options.buttonClasses]; + } + + if (typeof options.buttonClasses === 'object') { + this.buttonClasses = options.buttonClasses; + } + + if (typeof options.showDropdowns === 'boolean') { + this.showDropdowns = options.showDropdowns; + } + + if (typeof options.singleDatePicker === 'boolean') { + this.singleDatePicker = options.singleDatePicker; + } + + if (typeof options.timePicker === 'boolean') { + this.timePicker = options.timePicker; + } + + if (typeof options.timePickerIncrement === 'number') { + this.timePickerIncrement = options.timePickerIncrement; + } + + if (typeof options.timePicker12Hour === 'boolean') { + this.timePicker12Hour = options.timePicker12Hour; + } + + var start, end, range; + + //if no start/end dates set, check if an input element contains initial values + if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { + if ($(this.element).is('input[type=text]')) { + var val = $(this.element).val(); + var split = val.split(this.separator); + start = end = null; + if (split.length == 2) { + start = moment(split[0], this.format); + end = moment(split[1], this.format); + } else if (this.singleDatePicker) { + start = moment(val, this.format); + end = moment(val, this.format); + } + if (start !== null && end !== null) { + this.startDate = start; + this.endDate = end; + } + } + } + + if (typeof options.ranges === 'object') { + for (range in options.ranges) { + + start = moment(options.ranges[range][0]); + end = moment(options.ranges[range][1]); + + // If we have a min/max date set, bound this range + // to it, but only if it would otherwise fall + // outside of the min/max. + if (this.minDate && start.isBefore(this.minDate)) + start = moment(this.minDate); + + if (this.maxDate && end.isAfter(this.maxDate)) + end = moment(this.maxDate); + + // If the end of the range is before the minimum (if min is set) OR + // the start of the range is after the max (also if set) don't display this + // range option. + if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) { + continue; + } + + this.ranges[range] = [start, end]; + } + + var list = ''; + this.container.find('.ranges ul').remove(); + this.container.find('.ranges').prepend(list); + } + + if (typeof callback === 'function') { + this.cb = callback; + } + + if (!this.timePicker) { + this.startDate = this.startDate.startOf('day'); + this.endDate = this.endDate.endOf('day'); + } + + if (this.singleDatePicker) { + this.opens = 'right'; + this.container.find('.calendar.right').show(); + this.container.find('.calendar.left').hide(); + this.container.find('.ranges').hide(); + if (!this.container.find('.calendar.right').hasClass('single')) + this.container.find('.calendar.right').addClass('single'); + } else { + this.container.find('.calendar.right').removeClass('single'); + this.container.find('.ranges').show(); + } + + this.oldStartDate = this.startDate.clone(); + this.oldEndDate = this.endDate.clone(); + this.oldChosenLabel = this.chosenLabel; + + this.leftCalendar = { + month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]), + calendar: [] + }; + + this.rightCalendar = { + month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]), + calendar: [] + }; + + if (this.opens == 'right') { + //swap calendar positions + var left = this.container.find('.calendar.left'); + var right = this.container.find('.calendar.right'); + left.removeClass('left').addClass('right'); + right.removeClass('right').addClass('left'); + } + + if (typeof options.ranges === 'undefined' && !this.singleDatePicker) { + this.container.addClass('show-calendar'); + } + + this.container.addClass('opens' + this.opens); + + this.updateView(); + this.updateCalendars(); + + }, + + setStartDate: function(startDate) { + if (typeof startDate === 'string') + this.startDate = moment(startDate, this.format); + + if (typeof startDate === 'object') + this.startDate = moment(startDate); + + if (!this.timePicker) + this.startDate = this.startDate.startOf('day'); + + this.oldStartDate = this.startDate.clone(); + + this.updateView(); + this.updateCalendars(); + }, + + setEndDate: function(endDate) { + if (typeof endDate === 'string') + this.endDate = moment(endDate, this.format); + + if (typeof endDate === 'object') + this.endDate = moment(endDate); + + if (!this.timePicker) + this.endDate = this.endDate.endOf('day'); + + this.oldEndDate = this.endDate.clone(); + + this.updateView(); + this.updateCalendars(); + }, + + updateView: function () { + this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()); + this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()); + this.updateFormInputs(); + }, + + updateFormInputs: function () { + this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format)); + this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format)); + + if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) { + this.container.find('button.applyBtn').removeAttr('disabled'); + } else { + this.container.find('button.applyBtn').attr('disabled', 'disabled'); + } + }, + + updateFromControl: function () { + if (!this.element.is('input')) return; + if (!this.element.val().length) return; + + var dateString = this.element.val().split(this.separator); + var start = moment(dateString[0], this.format); + var end = moment(dateString[1], this.format); + + if (this.singleDatePicker) { + start = moment(this.element.val(), this.format); + end = start; + } + + if (end.isBefore(start)) return; + + this.oldStartDate = this.startDate.clone(); + this.oldEndDate = this.endDate.clone(); + + this.startDate = start; + this.endDate = end; + + if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) + this.notify(); + + this.updateCalendars(); + }, + + notify: function () { + this.updateView(); + this.cb(this.startDate, this.endDate, this.chosenLabel); + }, + + move: function () { + var parentOffset = { top: 0, left: 0 }; + if (!this.parentEl.is('body')) { + parentOffset = { + top: this.parentEl.offset().top - this.parentEl.scrollTop(), + left: this.parentEl.offset().left - this.parentEl.scrollLeft() + }; + } + + if (this.opens == 'left') { + this.container.css({ + top: this.element.offset().top + this.element.outerHeight() - parentOffset.top, + right: $(window).width() - this.element.offset().left - this.element.outerWidth() - parentOffset.left, + left: 'auto' + }); + if (this.container.offset().left < 0) { + this.container.css({ + right: 'auto', + left: 9 + }); + } + } else { + this.container.css({ + top: this.element.offset().top + this.element.outerHeight() - parentOffset.top, + left: this.element.offset().left - parentOffset.left, + right: 'auto' + }); + if (this.container.offset().left + this.container.outerWidth() > $(window).width()) { + this.container.css({ + left: 'auto', + right: 0 + }); + } + } + }, + + toggle: function (e) { + if (this.element.hasClass('active')) { + this.hide(); + } else { + this.show(); + } + }, + + show: function (e) { + this.element.addClass('active'); + this.container.show(); + this.move(); + + $(document).on('click.daterangepicker', $.proxy(this.outsideClick, this)); + // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them + $(document).on('click.daterangepicker', '[data-toggle=dropdown]', $.proxy(this.outsideClick, this)); + + this.element.trigger('show.daterangepicker', this); + }, + + outsideClick: function (e) { + var target = $(e.target); + // if the page is clicked anywhere except within the daterangerpicker/button + // itself then call this.hide() + if ( + target.closest(this.element).length || + target.closest(this.container).length || + target.closest('.calendar-date').length + ) return; + this.hide(); + }, + + hide: function (e) { + this.element.removeClass('active'); + this.container.hide(); + + if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) + this.notify(); + + this.oldStartDate = this.startDate.clone(); + this.oldEndDate = this.endDate.clone(); + + $(document).off('click.daterangepicker', this.outsideClick); + this.element.trigger('hide.daterangepicker', this); + }, + + enterRange: function (e) { + // mouse pointer has entered a range label + var label = e.target.innerHTML; + if (label == this.locale.customRangeLabel) { + this.updateView(); + } else { + var dates = this.ranges[label]; + this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format)); + this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format)); + } + }, + + showCalendars: function() { + this.container.addClass('show-calendar'); + this.move(); + }, + + hideCalendars: function() { + this.container.removeClass('show-calendar'); + }, + + updateInputText: function() { + if (this.element.is('input') && !this.singleDatePicker) { + this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format)); + } else if (this.element.is('input')) { + this.element.val(this.startDate.format(this.format)); + } + }, + + clickRange: function (e) { + var label = e.target.innerHTML; + this.chosenLabel = label; + if (label == this.locale.customRangeLabel) { + this.showCalendars(); + } else { + var dates = this.ranges[label]; + + this.startDate = dates[0]; + this.endDate = dates[1]; + + if (!this.timePicker) { + this.startDate.startOf('day'); + this.endDate.endOf('day'); + } + + this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute()); + this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute()); + this.updateCalendars(); + + this.updateInputText(); + + this.hideCalendars(); + this.hide(); + this.element.trigger('apply.daterangepicker', this); + } + }, + + clickPrev: function (e) { + var cal = $(e.target).parents('.calendar'); + if (cal.hasClass('left')) { + this.leftCalendar.month.subtract('month', 1); + } else { + this.rightCalendar.month.subtract('month', 1); + } + this.updateCalendars(); + }, + + clickNext: function (e) { + var cal = $(e.target).parents('.calendar'); + if (cal.hasClass('left')) { + this.leftCalendar.month.add('month', 1); + } else { + this.rightCalendar.month.add('month', 1); + } + this.updateCalendars(); + }, + + enterDate: function (e) { + + var title = $(e.target).attr('data-title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(e.target).parents('.calendar'); + + if (cal.hasClass('left')) { + this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format)); + } else { + this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format)); + } + + }, + + clickDate: function (e) { + var title = $(e.target).attr('data-title'); + var row = title.substr(1, 1); + var col = title.substr(3, 1); + var cal = $(e.target).parents('.calendar'); + + var startDate, endDate; + if (cal.hasClass('left')) { + startDate = this.leftCalendar.calendar[row][col]; + endDate = this.endDate; + if (typeof this.dateLimit === 'object') { + var maxDate = moment(startDate).add(this.dateLimit).startOf('day'); + if (endDate.isAfter(maxDate)) { + endDate = maxDate; + } + } + } else { + startDate = this.startDate; + endDate = this.rightCalendar.calendar[row][col]; + if (typeof this.dateLimit === 'object') { + var minDate = moment(endDate).subtract(this.dateLimit).startOf('day'); + if (startDate.isBefore(minDate)) { + startDate = minDate; + } + } + } + + if (this.singleDatePicker && cal.hasClass('left')) { + endDate = startDate.clone(); + } else if (this.singleDatePicker && cal.hasClass('right')) { + startDate = endDate.clone(); + } + + cal.find('td').removeClass('active'); + + if (startDate.isSame(endDate) || startDate.isBefore(endDate)) { + $(e.target).addClass('active'); + this.startDate = startDate; + this.endDate = endDate; + this.chosenLabel = this.locale.customRangeLabel; + } else if (startDate.isAfter(endDate)) { + $(e.target).addClass('active'); + var difference = this.endDate.diff(this.startDate); + this.startDate = startDate; + this.endDate = moment(startDate).add('ms', difference); + this.chosenLabel = this.locale.customRangeLabel; + } + + this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()); + this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()); + this.updateCalendars(); + + endDate.endOf('day'); + + if (this.singleDatePicker) + this.clickApply(); + }, + + clickApply: function (e) { + this.updateInputText(); + this.hide(); + this.element.trigger('apply.daterangepicker', this); + }, + + clickCancel: function (e) { + this.startDate = this.oldStartDate; + this.endDate = this.oldEndDate; + this.chosenLabel = this.oldChosenLabel; + this.updateView(); + this.updateCalendars(); + this.hide(); + this.element.trigger('cancel.daterangepicker', this); + }, + + updateMonthYear: function (e) { + var isLeft = $(e.target).closest('.calendar').hasClass('left'), + leftOrRight = isLeft ? 'left' : 'right', + cal = this.container.find('.calendar.'+leftOrRight); + + // Month must be Number for new moment versions + var month = parseInt(cal.find('.monthselect').val(), 10); + var year = cal.find('.yearselect').val(); + + this[leftOrRight+'Calendar'].month.month(month).year(year); + this.updateCalendars(); + }, + + updateTime: function(e) { + var isLeft = $(e.target).closest('.calendar').hasClass('left'), + leftOrRight = isLeft ? 'left' : 'right', + cal = this.container.find('.calendar.'+leftOrRight); + + var hour = parseInt(cal.find('.hourselect').val(), 10); + var minute = parseInt(cal.find('.minuteselect').val(), 10); + + if (this.timePicker12Hour) { + var ampm = cal.find('.ampmselect').val(); + if (ampm === 'PM' && hour < 12) + hour += 12; + if (ampm === 'AM' && hour === 12) + hour = 0; + } + + if (isLeft) { + var start = this.startDate.clone(); + start.hour(hour); + start.minute(minute); + this.startDate = start; + this.leftCalendar.month.hour(hour).minute(minute); + } else { + var end = this.endDate.clone(); + end.hour(hour); + end.minute(minute); + this.endDate = end; + this.rightCalendar.month.hour(hour).minute(minute); + } + + this.updateCalendars(); + }, + + updateCalendars: function () { + this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left'); + this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right'); + this.container.find('.calendar.left').html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate)); + this.container.find('.calendar.right').html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate)); + + this.container.find('.ranges li').removeClass('active'); + var customRange = true; + var i = 0; + for (var range in this.ranges) { + if (this.timePicker) { + if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) { + customRange = false; + this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')') + .addClass('active').html(); + } + } else { + //ignore times when comparing dates if time picker is not enabled + if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) { + customRange = false; + this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')') + .addClass('active').html(); + } + } + i++; + } + if (customRange) { + this.chosenLabel = this.container.find('.ranges li:last') + .addClass('active').html(); + } + }, + + buildCalendar: function (month, year, hour, minute, side) { + var firstDay = moment([year, month, 1]); + var lastMonth = moment(firstDay).subtract('month', 1).month(); + var lastYear = moment(firstDay).subtract('month', 1).year(); + + var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth(); + + var dayOfWeek = firstDay.day(); + + var i; + + //initialize a 6 rows x 7 columns array for the calendar + var calendar = []; + for (i = 0; i < 6; i++) { + calendar[i] = []; + } + + //populate the calendar with date objects + var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1; + if (startDay > daysInLastMonth) + startDay -= 7; + + if (dayOfWeek == this.locale.firstDay) + startDay = daysInLastMonth - 6; + + var curDate = moment([lastYear, lastMonth, startDay, 12, minute]); + var col, row; + for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) { + if (i > 0 && col % 7 === 0) { + col = 0; + row++; + } + calendar[row][col] = curDate.clone().hour(hour); + curDate.hour(12); + } + + return calendar; + }, + + renderDropdowns: function (selected, minDate, maxDate) { + var currentMonth = selected.month(); + var monthHtml = '"; + + var currentYear = selected.year(); + var maxYear = (maxDate && maxDate.year()) || (currentYear + 5); + var minYear = (minDate && minDate.year()) || (currentYear - 50); + var yearHtml = ''; + + return monthHtml + yearHtml; + }, + + renderCalendar: function (calendar, selected, minDate, maxDate) { + + var html = '
'; + html += ''; + html += ''; + html += ''; + + // add empty cell for week number + if (this.showWeekNumbers) + html += ''; + + if (!minDate || minDate.isBefore(calendar[1][1])) { + html += ''; + } else { + html += ''; + } + + var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY"); + + if (this.showDropdowns) { + dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate); + } + + html += ''; + if (!maxDate || maxDate.isAfter(calendar[1][1])) { + html += ''; + } else { + html += ''; + } + + html += ''; + html += ''; + + // add week number label + if (this.showWeekNumbers) + html += ''; + + $.each(this.locale.daysOfWeek, function (index, dayOfWeek) { + html += ''; + }); + + html += ''; + html += ''; + html += ''; + + for (var row = 0; row < 6; row++) { + html += ''; + + // add week number + if (this.showWeekNumbers) + html += ''; + + for (var col = 0; col < 7; col++) { + var cname = 'available '; + cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off'; + + if ((minDate && calendar[row][col].isBefore(minDate)) || (maxDate && calendar[row][col].isAfter(maxDate))) { + cname = ' off disabled '; + } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) { + cname += ' active '; + if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) { + cname += ' start-date '; + } + if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) { + cname += ' end-date '; + } + } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) { + cname += ' in-range '; + if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; } + if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; } + } + + var title = 'r' + row + 'c' + col; + html += ''; + } + html += ''; + } + + html += ''; + html += '
' + dateHtml + '
' + this.locale.weekLabel + '' + dayOfWeek + '
' + calendar[row][0].week() + '' + calendar[row][col].date() + '
'; + html += '
'; + + var i; + if (this.timePicker) { + + html += '
'; + html += ' : '; + + html += ' '; + + if (this.timePicker12Hour) { + html += ''; + } + + html += '
'; + + } + + return html; + + }, + + remove: function() { + + this.container.remove(); + this.element.off('.daterangepicker'); + this.element.removeData('daterangepicker'); + + } + + }; + + $.fn.daterangepicker = function (options, cb) { + this.each(function () { + var el = $(this); + if (el.data('daterangepicker')) + el.data('daterangepicker').remove(); + el.data('daterangepicker', new DateRangePicker(el, options, cb)); + }); + return this; + }; + +}(window.jQuery, window.moment); diff --git a/main/inc/lib/javascript/daterange/moment.min.js b/main/inc/lib/javascript/daterange/moment.min.js new file mode 100644 index 0000000000..78e51c215b --- /dev/null +++ b/main/inc/lib/javascript/daterange/moment.min.js @@ -0,0 +1,9 @@ +//! moment.js +//! version : 2.5.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +(function(a){function b(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function c(a,b){return function(c){return k(a.call(this,c),b)}}function d(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function e(){}function f(a){w(a),h(this,a)}function g(a){var b=q(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._milliseconds=+j+1e3*i+6e4*h+36e5*g,this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function h(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function i(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&qb.hasOwnProperty(b)&&(c[b]=a[b]);return c}function j(a){return 0>a?Math.ceil(a):Math.floor(a)}function k(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&s(a[d])!==s(b[d]))&&g++;return g+f}function p(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Tb[a]||Ub[b]||b}return a}function q(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=p(c),b&&(d[b]=a[c]));return d}function r(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}db[b]=function(e,f){var g,h,i=db.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=db().utc().set(d,a);return i.call(db.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function s(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function t(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function u(a){return v(a)?366:365}function v(a){return a%4===0&&a%100!==0||a%400===0}function w(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[jb]<0||a._a[jb]>11?jb:a._a[kb]<1||a._a[kb]>t(a._a[ib],a._a[jb])?kb:a._a[lb]<0||a._a[lb]>23?lb:a._a[mb]<0||a._a[mb]>59?mb:a._a[nb]<0||a._a[nb]>59?nb:a._a[ob]<0||a._a[ob]>999?ob:-1,a._pf._overflowDayOfYear&&(ib>b||b>kb)&&(b=kb),a._pf.overflow=b)}function x(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function y(a){return a?a.toLowerCase().replace("_","-"):a}function z(a,b){return b._isUTC?db(a).zone(b._offset||0):db(a).local()}function A(a,b){return b.abbr=a,pb[a]||(pb[a]=new e),pb[a].set(b),pb[a]}function B(a){delete pb[a]}function C(a){var b,c,d,e,f=0,g=function(a){if(!pb[a]&&rb)try{require("./lang/"+a)}catch(b){}return pb[a]};if(!a)return db.fn._lang;if(!m(a)){if(c=g(a))return c;a=[a]}for(;f0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&o(e,d,!0)>=b-1)break;b--}f++}return db.fn._lang}function D(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function E(a){var b,c,d=a.match(vb);for(b=0,c=d.length;c>b;b++)d[b]=Yb[d[b]]?Yb[d[b]]:D(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function F(a,b){return a.isValid()?(b=G(b,a.lang()),Vb[b]||(Vb[b]=E(b)),Vb[b](a)):a.lang().invalidDate()}function G(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(wb.lastIndex=0;d>=0&&wb.test(a);)a=a.replace(wb,c),wb.lastIndex=0,d-=1;return a}function H(a,b){var c,d=b._strict;switch(a){case"DDDD":return Ib;case"YYYY":case"GGGG":case"gggg":return d?Jb:zb;case"Y":case"G":case"g":return Lb;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?Kb:Ab;case"S":if(d)return Gb;case"SS":if(d)return Hb;case"SSS":if(d)return Ib;case"DDD":return yb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Cb;case"a":case"A":return C(b._l)._meridiemParse;case"X":return Fb;case"Z":case"ZZ":return Db;case"T":return Eb;case"SSSS":return Bb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?Hb:xb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return xb;default:return c=new RegExp(P(O(a.replace("\\","")),"i"))}}function I(a){a=a||"";var b=a.match(Db)||[],c=b[b.length-1]||[],d=(c+"").match(Qb)||["-",0,0],e=+(60*d[1])+s(d[2]);return"+"===d[0]?-e:e}function J(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[jb]=s(b)-1);break;case"MMM":case"MMMM":d=C(c._l).monthsParse(b),null!=d?e[jb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[kb]=s(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=s(b));break;case"YY":e[ib]=s(b)+(s(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":case"YYYYYY":e[ib]=s(b);break;case"a":case"A":c._isPm=C(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[lb]=s(b);break;case"m":case"mm":e[mb]=s(b);break;case"s":case"ss":e[nb]=s(b);break;case"S":case"SS":case"SSS":case"SSSS":e[ob]=s(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=I(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function K(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=M(a),a._w&&null==a._a[kb]&&null==a._a[jb]&&(f=function(b){var c=parseInt(b,10);return b?b.length<3?c>68?1900+c:2e3+c:c:null==a._a[ib]?db().weekYear():a._a[ib]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=Z(f(g.GG),g.W||1,g.E,4,1):(i=C(a._l),j=null!=g.d?V(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&ju(e)&&(a._pf._overflowDayOfYear=!0),c=U(e,0,a._dayOfYear),a._a[jb]=c.getUTCMonth(),a._a[kb]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[lb]+=s((a._tzm||0)/60),l[mb]+=s((a._tzm||0)%60),a._d=(a._useUTC?U:T).apply(null,l)}}function L(a){var b;a._d||(b=q(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],K(a))}function M(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function N(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=C(a._l),h=""+a._i,i=h.length,j=0;for(d=G(a._f,g).match(vb)||[],b=0;b0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Yb[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),J(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[lb]<12&&(a._a[lb]+=12),a._isPm===!1&&12===a._a[lb]&&(a._a[lb]=0),K(a),w(a)}function O(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function P(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a){var c,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,a._d=new Date(0/0),void 0;for(f=0;fg)&&(e=g,d=c));h(a,d||c)}function R(a){var b,c,d=a._i,e=Mb.exec(d);if(e){for(a._pf.iso=!0,b=0,c=Ob.length;c>b;b++)if(Ob[b][1].exec(d)){a._f=Ob[b][0]+(e[6]||" ");break}for(b=0,c=Pb.length;c>b;b++)if(Pb[b][1].exec(d)){a._f+=Pb[b][0];break}d.match(Db)&&(a._f+="Z"),N(a)}else a._d=new Date(d)}function S(b){var c=b._i,d=sb.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?R(b):m(c)?(b._a=c.slice(0),K(b)):n(c)?b._d=new Date(+c):"object"==typeof c?L(b):b._d=new Date(c)}function T(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function U(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function V(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function W(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function X(a,b,c){var d=hb(Math.abs(a)/1e3),e=hb(d/60),f=hb(e/60),g=hb(f/24),h=hb(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",hb(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,W.apply({},i)}function Y(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=db(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function Z(a,b,c,d,e){var f,g,h=U(a,0,1).getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:u(a-1)+g}}function $(a){var b=a._i,c=a._f;return null===b?db.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=C().preparse(b)),db.isMoment(b)?(a=i(b),a._d=new Date(+b._d)):c?m(c)?Q(a):N(a):S(a),new f(a))}function _(a,b){db.fn[a]=db.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),db.updateOffset(this),this):this._d["get"+c+b]()}}function ab(a){db.duration.fn[a]=function(){return this._data[a]}}function bb(a,b){db.duration.fn["as"+a]=function(){return+this/b}}function cb(a){var b=!1,c=db;"undefined"==typeof ender&&(a?(gb.moment=function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)},h(gb.moment,c)):gb.moment=db)}for(var db,eb,fb="2.5.1",gb=this,hb=Math.round,ib=0,jb=1,kb=2,lb=3,mb=4,nb=5,ob=6,pb={},qb={_isAMomentObject:null,_i:null,_f:null,_l:null,_strict:null,_isUTC:null,_offset:null,_pf:null,_lang:null},rb="undefined"!=typeof module&&module.exports&&"undefined"!=typeof require,sb=/^\/?Date\((\-?\d+)/i,tb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,ub=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,vb=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,wb=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,xb=/\d\d?/,yb=/\d{1,3}/,zb=/\d{1,4}/,Ab=/[+\-]?\d{1,6}/,Bb=/\d+/,Cb=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Db=/Z|[\+\-]\d\d:?\d\d/gi,Eb=/T/i,Fb=/[\+\-]?\d+(\.\d{1,3})?/,Gb=/\d/,Hb=/\d\d/,Ib=/\d{3}/,Jb=/\d{4}/,Kb=/[+-]?\d{6}/,Lb=/[+-]?\d+/,Mb=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Nb="YYYY-MM-DDTHH:mm:ssZ",Ob=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],Pb=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Qb=/([\+\-]|\d\d)/gi,Rb="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Sb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Tb={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Ub={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Vb={},Wb="DDD w W M D d".split(" "),Xb="M D H h m s w W".split(" "),Yb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return k(this.year()%100,2)},YYYY:function(){return k(this.year(),4)},YYYYY:function(){return k(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+k(Math.abs(a),6)},gg:function(){return k(this.weekYear()%100,2)},gggg:function(){return k(this.weekYear(),4)},ggggg:function(){return k(this.weekYear(),5)},GG:function(){return k(this.isoWeekYear()%100,2)},GGGG:function(){return k(this.isoWeekYear(),4)},GGGGG:function(){return k(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return s(this.milliseconds()/100)},SS:function(){return k(s(this.milliseconds()/10),2)},SSS:function(){return k(this.milliseconds(),3)},SSSS:function(){return k(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+":"+k(s(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+k(s(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Zb=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Wb.length;)eb=Wb.pop(),Yb[eb+"o"]=d(Yb[eb],eb);for(;Xb.length;)eb=Xb.pop(),Yb[eb+eb]=c(Yb[eb],2);for(Yb.DDDD=c(Yb.DDD,3),h(e.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=db.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=db([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return Y(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),db=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=c,g._f=d,g._l=e,g._strict=f,g._isUTC=!1,g._pf=b(),$(g)},db.utc=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=c,g._f=d,g._strict=f,g._pf=b(),$(g).utc()},db.unix=function(a){return db(1e3*a)},db.duration=function(a,b){var c,d,e,f=a,h=null;return db.isDuration(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=tb.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:s(h[kb])*c,h:s(h[lb])*c,m:s(h[mb])*c,s:s(h[nb])*c,ms:s(h[ob])*c}):(h=ub.exec(a))&&(c="-"===h[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},f={y:e(h[2]),M:e(h[3]),d:e(h[4]),h:e(h[5]),m:e(h[6]),s:e(h[7]),w:e(h[8])}),d=new g(f),db.isDuration(a)&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},db.version=fb,db.defaultFormat=Nb,db.updateOffset=function(){},db.lang=function(a,b){var c;return a?(b?A(y(a),b):null===b?(B(a),a="en"):pb[a]||C(a),c=db.duration.fn._lang=db.fn._lang=C(a),c._abbr):db.fn._lang._abbr},db.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),C(a)},db.isMoment=function(a){return a instanceof f||null!=a&&a.hasOwnProperty("_isAMomentObject")},db.isDuration=function(a){return a instanceof g},eb=Zb.length-1;eb>=0;--eb)r(Zb[eb]);for(db.normalizeUnits=function(a){return p(a)},db.invalid=function(a){var b=db.utc(0/0);return null!=a?h(b._pf,a):b._pf.userInvalidated=!0,b},db.parseZone=function(a){return db(a).parseZone()},h(db.fn=f.prototype,{clone:function(){return db(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=db(this).utc();return 00:!1},parsingFlags:function(){return h({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=F(this,a||db.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,-1),this},diff:function(a,b,c){var d,e,f=z(a,this),g=6e4*(this.zone()-f.zone());return b=p(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-db(this).startOf("month")-(f-db(f).startOf("month")))/d,e-=6e4*(this.zone()-db(this).startOf("month").zone()-(f.zone()-db(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:j(e)},from:function(a,b){return db.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(db(),a)},calendar:function(){var a=z(db(),this).startOf("day"),b=this.diff(a,"days",!0),c=-6>b?"sameElse":-1>b?"lastWeek":0>b?"lastDay":1>b?"sameDay":2>b?"nextDay":7>b?"nextWeek":"sameElse";return this.format(this.lang().calendar(c,this))},isLeapYear:function(){return v(this.year())},isDST:function(){return this.zone()+db(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+db(a).startOf(b)},isSame:function(a,b){return b=b||"ms",+this.clone().startOf(b)===+z(a,this).startOf(b)},min:function(a){return a=db.apply(null,arguments),this>a?this:a},max:function(a){return a=db.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=I(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&l(this,db.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?db(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return t(this.year(),this.month())},dayOfYear:function(a){var b=hb((db(this).startOf("day")-db(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},quarter:function(){return Math.ceil((this.month()+1)/3)},weekYear:function(a){var b=Y(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=Y(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=Y(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=p(a),this[a]()},set:function(a,b){return a=p(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=C(b),this)}}),eb=0;eb10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(b){function c(a,b,c){var d={mm:"munutenn",MM:"miz",dd:"devezh"};return a+" "+f(d[c],a)}function d(a){switch(e(a)){case 1:case 3:case 4:case 5:case 9:return a+" bloaz";default:return a+" vloaz"}}function e(a){return a>9?e(a%10):a}function f(a,b){return 2===b?g(a):a}function g(b){var c={m:"v",b:"v",d:"z"};return c[b.charAt(0)]===a?b:c[b.charAt(0)]+b.substring(1)}return b.lang("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),longDateFormat:{LT:"h[e]mm A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY LT",LLLL:"dddd, D [a viz] MMMM YYYY LT"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondennoù",m:"ur vunutenn",mm:c,h:"un eur",hh:"%d eur",d:"un devezh",dd:c,M:"ur miz",MM:c,y:"ur bloaz",yy:d},ordinal:function(a){var b=1===a?"añ":"vet";return a+b},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}return a.lang("bs",{months:"januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[proÅ¡lu] dddd [u] LT";case 6:return"[proÅ¡le] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[proÅ¡li] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:b,mm:b,h:b,hh:b,d:"dan",dd:b,M:"mjesec",MM:b,y:"godinu",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("ca",{months:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),monthsShort:"gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT" +},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a){return a>1&&5>a&&1!==~~(a/10)}function c(a,c,d,e){var f=a+" ";switch(d){case"s":return c||e?"pár vteÅ™in":"pár vteÅ™inami";case"m":return c?"minuta":e?"minutu":"minutou";case"mm":return c||e?f+(b(a)?"minuty":"minut"):f+"minutami";break;case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(b(a)?"hodiny":"hodin"):f+"hodinami";break;case"d":return c||e?"den":"dnem";case"dd":return c||e?f+(b(a)?"dny":"dní"):f+"dny";break;case"M":return c||e?"mÄ›síc":"mÄ›sícem";case"MM":return c||e?f+(b(a)?"mÄ›síce":"mÄ›síců"):f+"mÄ›síci";break;case"y":return c||e?"rok":"rokem";case"yy":return c||e?f+(b(a)?"roky":"let"):f+"lety"}}var d="leden_únor_bÅ™ezen_duben_kvÄ›ten_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),e="led_úno_bÅ™e_dub_kvÄ›_čvn_čvc_srp_zář_říj_lis_pro".split("_");return a.lang("cs",{months:d,monthsShort:e,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(d,e),weekdays:"nedÄ›le_pondÄ›lí_úterý_stÅ™eda_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedÄ›li v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve stÅ™edu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou nedÄ›li v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou stÅ™edu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pÅ™ed %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("cv",{months:"кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),monthsShort:"кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),weekdaysMin:"вр_тн_Ñ‹Ñ‚_юн_кç_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]",LLL:"YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT",LLLL:"dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ĕнер] LT [сехетре]",nextWeek:"[Çитес] dddd LT [сехетре]",lastWeek:"[Иртнĕ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(a){var b=/сехет$/i.exec(a)?"рен":/çул$/i.exec(a)?"тан":"ран";return a+b},past:"%s каялла",s:"пĕр-ик çеккунт",m:"пĕр минут",mm:"%d минут",h:"пĕр сехет",hh:"%d сехет",d:"пĕр кун",dd:"%d кун",M:"пĕр уйăх",MM:"%d уйăх",y:"пĕр çул",yy:"%d çул"},ordinal:"%d-мĕш",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn à l",s:"ychydig eiliadau",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},ordinal:function(a){var b=a,c="",d=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed","eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"];return b>20?c=40===b||50===b||60===b||80===b||100===b?"fed":"ain":b>0&&(c=d[b]),a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D. MMMM, YYYY LT"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I gÃ¥r kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"fÃ¥ sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en mÃ¥ned",MM:"%d mÃ¥neder",y:"et Ã¥r",yy:"%d Ã¥r"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?d[c][0]:d[c][1]}return a.lang("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm [Uhr]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:b,mm:"%d Minuten",h:b,hh:"%d Stunden",d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"Î Îœ"},longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:"[την προηγούμενη] dddd [{}] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendarEl[a],d=b&&b.hours();return c.replace("{}",d%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinal:function(a){return a+"η"},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}})}),function(a){a(db)}(function(a){return a.lang("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aÅ­gusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aÅ­g_sep_okt_nov_dec".split("_"),weekdays:"Dimanĉo_Lundo_Mardo_Merkredo_Ä´aÅ­do_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Mard_Merk_Ä´aÅ­_Ven_Sab".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Ä´a_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D[-an de] MMMM, YYYY",LLL:"D[-an de] MMMM, YYYY LT",LLLL:"dddd, [la] D[-an de] MMMM, YYYY LT"},meridiem:function(a,b,c){return a>11?c?"p.t.m.":"P.T.M.":c?"a.t.m.":"A.T.M."},calendar:{sameDay:"[HodiaÅ­ je] LT",nextDay:"[MorgaÅ­ je] LT",nextWeek:"dddd [je] LT",lastDay:"[HieraÅ­ je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"je %s",past:"antaÅ­ %s",s:"sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},ordinal:"%da",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c,d){var e={s:["mõne sekundi","mõni sekund","paar sekundit"],m:["ühe minuti","üks minut"],mm:[a+" minuti",a+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[a+" tunni",a+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[a+" kuu",a+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[a+" aasta",a+" aastat"]};return b?e[c][2]?e[c][2]:e[c][1]:d?e[c][0]:e[c][1]}return a.lang("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:b,m:b,mm:b,h:b,hh:b,d:b,dd:"%d päeva",M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] LT",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] LT",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] LT",llll:"ddd, YYYY[ko] MMM D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){var b={1:"Û±",2:"Û²",3:"Û³",4:"Û´",5:"Ûµ",6:"Û¶",7:"Û·",8:"Û¸",9:"Û¹",0:"Û°"},c={"Û±":"1","Û²":"2","Û³":"3","Û´":"4","Ûµ":"5","Û¶":"6","Û·":"7","Û¸":"8","Û¹":"9","Û°":"0"};return a.lang("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ÛŒ_د_س_Ú†_Ù¾_ج_Ø´".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},meridiem:function(a){return 12>a?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[Û°-Û¹]/g,function(a){return c[a]}).replace(/ØŒ/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return b[a]}).replace(/,/g,"ØŒ")},ordinal:"%dÙ…",week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){function b(a,b,d,e){var f="";switch(d){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=c(a,e)+" "+f}function c(a,b){return 10>a?b?e[a]:d[a]:a}var d="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),e=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",d[7],d[8],d[9]];return a.lang("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] LT",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] LT",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] LT",llll:"ddd, Do MMM YYYY, [klo] LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:b,m:b,mm:b,h:b,hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("fo",{months:"januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),weekdaysShort:"sun_mán_týs_mik_hós_frí_ley".split("_"),weekdaysMin:"su_má_tý_mi_hó_fr_le".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D. MMMM, YYYY LT"},calendar:{sameDay:"[Í dag kl.] LT",nextDay:"[Í morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[Í gjár kl.] LT",lastWeek:"[síðstu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s síðani",s:"fá sekund",m:"ein minutt",mm:"%d minuttir",h:"ein tími",hh:"%d tímar",d:"ein dagur",dd:"%d dagar",M:"ein mánaði",MM:"%d mánaðir",y:"eitt ár",yy:"%d ár"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à ] LT",nextDay:"[Demain à ] LT",nextWeek:"dddd [à ] LT",lastDay:"[Hier à ] LT",lastWeek:"dddd [dernier à ] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(a){return a+(1===a?"er":"")}})}),function(a){a(db)}(function(a){return a.lang("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à ] LT",nextDay:"[Demain à ] LT",nextWeek:"dddd [à ] LT",lastDay:"[Hier à ] LT",lastWeek:"dddd [dernier à ] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(a){return"uns segundos"===a?"nuns segundos":"en "+a},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:"%dº",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("he",{months:"×™× ×•××¨_פברואר_מרץ_אפריל_מאי_×™×•× ×™_יולי_אוגוסט_ספטמבר_אוקטובר_× ×•×‘×ž×‘×¨_דצמבר".split("_"),monthsShort:"×™× ×•×³_פבר׳_מרץ_אפר׳_מאי_×™×•× ×™_יולי_אוג׳_ספט׳_אוק׳_× ×•×‘×³_דצמ׳".split("_"),weekdays:"ראשון_×©× ×™_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_×’_ד_×”_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY LT",LLLL:"dddd, D [ב]MMMM YYYY LT",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY LT",llll:"ddd, D MMM YYYY LT"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"×œ×¤× ×™ %s",s:"מספר ×©× ×™×•×ª",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(a){return 2===a?"שעתיים":a+" שעות"},d:"יום",dd:function(a){return 2===a?"יומיים":a+" ימים"},M:"חודש",MM:function(a){return 2===a?"חודשיים":a+" חודשים"},y:"×©× ×”",yy:function(a){return 2===a?"×©× ×ª×™×™×":a+" ×©× ×™×"}}})}),function(a){a(db)}(function(a){var b={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return a.lang("hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return b[a]})},meridiem:function(a){return 4>a?"रात":10>a?"सुबह":17>a?"दोपहर":20>a?"शाम":"रात"},week:{dow:0,doy:6}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}return a.lang("hr",{months:"sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_"),monthsShort:"sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[proÅ¡lu] dddd [u] LT";case 6:return"[proÅ¡le] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[proÅ¡li] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:b,mm:b,h:b,hh:b,d:"dan",dd:b,M:"mjesec",MM:b,y:"godinu",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function c(a){return(a?"":"[múlt] ")+"["+d[this.day()]+"] LT[-kor]"}var d="vasárnap hétfÅ‘n kedden szerdán csütörtökön pénteken szombaton".split(" ");return a.lang("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfÅ‘_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return c.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return c.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:b,m:b,mm:b,h:b,hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b){var c={nominative:"Õ°Õ¸Ö‚Õ¶Õ¾Õ¡Ö€_ÖƒÕ¥Õ¿Ö€Õ¾Õ¡Ö€_Õ´Õ¡Ö€Õ¿_Õ¡ÕºÖ€Õ«Õ¬_Õ´Õ¡ÕµÕ«Õ½_Õ°Õ¸Ö‚Õ¶Õ«Õ½_Õ°Õ¸Ö‚Õ¬Õ«Õ½_Ö…Õ£Õ¸Õ½Õ¿Õ¸Õ½_Õ½Õ¥ÕºÕ¿Õ¥Õ´Õ¢Õ¥Ö€_Õ°Õ¸Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€_Õ¶Õ¸ÕµÕ¥Õ´Õ¢Õ¥Ö€_Õ¤Õ¥Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€".split("_"),accusative:"Õ°Õ¸Ö‚Õ¶Õ¾Õ¡Ö€Õ«_ÖƒÕ¥Õ¿Ö€Õ¾Õ¡Ö€Õ«_Õ´Õ¡Ö€Õ¿Õ«_Õ¡ÕºÖ€Õ«Õ¬Õ«_Õ´Õ¡ÕµÕ«Õ½Õ«_Õ°Õ¸Ö‚Õ¶Õ«Õ½Õ«_Õ°Õ¸Ö‚Õ¬Õ«Õ½Õ«_Ö…Õ£Õ¸Õ½Õ¿Õ¸Õ½Õ«_Õ½Õ¥ÕºÕ¿Õ¥Õ´Õ¢Õ¥Ö€Õ«_Õ°Õ¸Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€Õ«_Õ¶Õ¸ÕµÕ¥Õ´Õ¢Õ¥Ö€Õ«_Õ¤Õ¥Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€Õ«".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function c(a){var b="Õ°Õ¶Õ¾_ÖƒÕ¿Ö€_Õ´Ö€Õ¿_Õ¡ÕºÖ€_Õ´ÕµÕ½_Õ°Õ¶Õ½_Õ°Õ¬Õ½_Ö…Õ£Õ½_Õ½ÕºÕ¿_Õ°Õ¯Õ¿_Õ¶Õ´Õ¢_Õ¤Õ¯Õ¿".split("_");return b[a.month()]}function d(a){var b="Õ¯Õ«Ö€Õ¡Õ¯Õ«_Õ¥Ö€Õ¯Õ¸Ö‚Õ·Õ¡Õ¢Õ©Õ«_Õ¥Ö€Õ¥Ö„Õ·Õ¡Õ¢Õ©Õ«_Õ¹Õ¸Ö€Õ¥Ö„Õ·Õ¡Õ¢Õ©Õ«_Õ°Õ«Õ¶Õ£Õ·Õ¡Õ¢Õ©Õ«_Õ¸Ö‚Ö€Õ¢Õ¡Õ©_Õ·Õ¡Õ¢Õ¡Õ©".split("_");return b[a.day()]}return a.lang("hy-am",{months:b,monthsShort:c,weekdays:d,weekdaysShort:"Õ¯Ö€Õ¯_Õ¥Ö€Õ¯_Õ¥Ö€Ö„_Õ¹Ö€Ö„_Õ°Õ¶Õ£_Õ¸Ö‚Ö€Õ¢_Õ·Õ¢Õ©".split("_"),weekdaysMin:"Õ¯Ö€Õ¯_Õ¥Ö€Õ¯_Õ¥Ö€Ö„_Õ¹Ö€Ö„_Õ°Õ¶Õ£_Õ¸Ö‚Ö€Õ¢_Õ·Õ¢Õ©".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY Õ©.",LLL:"D MMMM YYYY Õ©., LT",LLLL:"dddd, D MMMM YYYY Õ©., LT"},calendar:{sameDay:"[Õ¡ÕµÕ½Ö…Ö€] LT",nextDay:"[Õ¾Õ¡Õ²Õ¨] LT",lastDay:"[Õ¥Ö€Õ¥Õ¯] LT",nextWeek:function(){return"dddd [Ö…Ö€Õ¨ ÕªÕ¡Õ´Õ¨] LT"},lastWeek:function(){return"[անցած] dddd [Ö…Ö€Õ¨ ÕªÕ¡Õ´Õ¨] LT"},sameElse:"L"},relativeTime:{future:"%s Õ°Õ¥Õ¿Õ¸",past:"%s Õ¡Õ¼Õ¡Õ»",s:"Õ´Õ« Ö„Õ¡Õ¶Õ« Õ¾Õ¡ÕµÖ€Õ¯ÕµÕ¡Õ¶",m:"Ö€Õ¸ÕºÕ¥",mm:"%d Ö€Õ¸ÕºÕ¥",h:"ÕªÕ¡Õ´",hh:"%d ÕªÕ¡Õ´",d:"Ö…Ö€",dd:"%d Ö…Ö€",M:"Õ¡Õ´Õ«Õ½",MM:"%d Õ¡Õ´Õ«Õ½",y:"Õ¿Õ¡Ö€Õ«",yy:"%d Õ¿Õ¡Ö€Õ«"},meridiem:function(a){return 4>a?"Õ£Õ«Õ·Õ¥Ö€Õ¾Õ¡":12>a?"Õ¡Õ¼Õ¡Õ¾Õ¸Õ¿Õ¾Õ¡":17>a?"ցերեկվա":"Õ¥Ö€Õ¥Õ¯Õ¸ÕµÕ¡Õ¶"},ordinal:function(a,b){switch(b){case"DDD":case"w":case"W":case"DDDo":return 1===a?a+"-Õ«Õ¶":a+"-Ö€Õ¤";default:return a}},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(a){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a){return a%100===11?!0:a%10===1?!1:!0}function c(a,c,d,e){var f=a+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return b(a)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return b(a)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return b(a)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return b(a)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return b(a)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}}return a.lang("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd, D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:c,m:c,mm:c,h:"klukkustund",hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:"%d.",week:{dow:1,doy:4}}) +}),function(a){a(db)}(function(a){return a.lang("it",{months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"æ—¥_月_火_æ°´_木_金_土".split("_"),weekdaysMin:"æ—¥_月_火_æ°´_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYYå¹´M月Dæ—¥",LLL:"YYYYå¹´M月Dæ—¥LT",LLLL:"YYYYå¹´M月Dæ—¥LT dddd"},meridiem:function(a){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1æ—¥",dd:"%dæ—¥",M:"1ヶ月",MM:"%dヶ月",y:"1å¹´",yy:"%då¹´"}})}),function(a){a(db)}(function(a){function b(a,b){var c={nominative:"იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი".split("_"),accusative:"იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს".split("_")},d=/D[oD] *MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function c(a,b){var c={nominative:"კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი".split("_"),accusative:"კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს".split("_")},d=/(წინა|შემდეგ)/.test(b)?"accusative":"nominative";return c[d][a.day()]}return a.lang("ka",{months:b,monthsShort:"იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),weekdays:c,weekdaysShort:"კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),weekdaysMin:"კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[დღეს] LT[-ზე]",nextDay:"[ხვალ] LT[-ზე]",lastDay:"[გუშინ] LT[-ზე]",nextWeek:"[შემდეგ] dddd LT[-ზე]",lastWeek:"[წინა] dddd LT-ზე",sameElse:"L"},relativeTime:{future:function(a){return/(წამი|წუთი|საათი|წელი)/.test(a)?a.replace(/ი$/,"ში"):a+"ში"},past:function(a){return/(წამი|წუთი|საათი|დღე|თვე)/.test(a)?a.replace(/(ი|ე)$/,"ის წინ"):/წელი/.test(a)?a.replace(/წელი$/,"წლის წინ"):void 0},s:"რამდენიმე წამი",m:"წუთი",mm:"%d წუთი",h:"საათი",hh:"%d საათი",d:"დღე",dd:"%d დღე",M:"თვე",MM:"%d თვე",y:"წელი",yy:"%d წელი"},ordinal:function(a){return 0===a?a:1===a?a+"-ლი":20>a||100>=a&&a%20===0||a%100===0?"მე-"+a:a+"-ე"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("ko",{months:"1ì›”_2ì›”_3ì›”_4ì›”_5ì›”_6ì›”_7ì›”_8ì›”_9ì›”_10ì›”_11ì›”_12ì›”".split("_"),monthsShort:"1ì›”_2ì›”_3ì›”_4ì›”_5ì›”_6ì›”_7ì›”_8ì›”_9ì›”_10ì›”_11ì›”_12ì›”".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_í† ìš”ì¼".split("_"),weekdaysShort:"일_ì›”_í™”_수_목_금_í† ".split("_"),weekdaysMin:"일_ì›”_í™”_수_목_금_í† ".split("_"),longDateFormat:{LT:"A hì‹œ mm분",L:"YYYY.MM.DD",LL:"YYYYë…„ MMMM D일",LLL:"YYYYë…„ MMMM D일 LT",LLLL:"YYYYë…„ MMMM D일 dddd LT"},meridiem:function(a){return 12>a?"ì˜¤ì „":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"ì–´ì œ LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s ì „",s:"몇초",ss:"%dì´ˆ",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%dë…„"},ordinal:"%d일",meridiemParse:/(ì˜¤ì „|오후)/,isPM:function(a){return"오후"===a}})}),function(a){a(db)}(function(a){function b(a,b,c){var d={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],dd:[a+" Deeg",a+" Deeg"],M:["ee Mount","engem Mount"],MM:[a+" Méint",a+" Méint"],y:["ee Joer","engem Joer"],yy:[a+" Joer",a+" Joer"]};return b?d[c][0]:d[c][1]}function c(a){var b=a.substr(0,a.indexOf(" "));return g(b)?"a "+a:"an "+a}function d(a){var b=a.substr(0,a.indexOf(" "));return g(b)?"viru "+a:"virun "+a}function e(){var a=this.format("d");return f(a)?"[Leschte] dddd [um] LT":"[Leschten] dddd [um] LT"}function f(a){switch(a=parseInt(a,10)){case 0:case 1:case 3:case 5:case 6:return!0;default:return!1}}function g(a){if(a=parseInt(a,10),isNaN(a))return!1;if(0>a)return!0;if(10>a)return a>=4&&7>=a?!0:!1;if(100>a){var b=a%10,c=a/10;return 0===b?g(c):g(b)}if(1e4>a){for(;a>=10;)a/=10;return g(a)}return a/=1e3,g(a)}return a.lang("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:e},relativeTime:{future:c,past:d,s:"e puer Sekonnen",m:b,mm:"%d Minutten",h:b,hh:"%d Stonnen",d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c,d){return b?"kelios sekundÄ—s":d?"kelių sekundžių":"kelias sekundes"}function c(a,b,c,d){return b?e(c)[0]:d?e(c)[1]:e(c)[2]}function d(a){return a%10===0||a>10&&20>a}function e(a){return h[a].split("_")}function f(a,b,f,g){var h=a+" ";return 1===a?h+c(a,b,f[0],g):b?h+(d(a)?e(f)[1]:e(f)[0]):g?h+e(f)[1]:h+(d(a)?e(f)[1]:e(f)[2])}function g(a,b){var c=-1===b.indexOf("dddd LT"),d=i[a.weekday()];return c?d:d.substring(0,d.length-2)+"į"}var h={m:"minutÄ—_minutÄ—s_minutÄ™",mm:"minutÄ—s_minučių_minutes",h:"valanda_valandos_valandÄ…",hh:"valandos_valandų_valandas",d:"diena_dienos_dienÄ…",dd:"dienos_dienų_dienas",M:"mÄ—nuo_mÄ—nesio_mÄ—nesį",MM:"mÄ—nesiai_mÄ—nesių_mÄ—nesius",y:"metai_metų_metus",yy:"metai_metų_metus"},i="pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_Å¡eÅ¡tadienis_sekmadienis".split("_");return a.lang("lt",{months:"sausio_vasario_kovo_balandžio_gegužės_biržėlio_liepos_rugpjūčio_rugsÄ—jo_spalio_lapkričio_gruodžio".split("_"),monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:g,weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Å eÅ¡".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Å ".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], LT [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, LT [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], LT [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, LT [val.]"},calendar:{sameDay:"[Å iandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[PraÄ—jusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieÅ¡ %s",s:b,m:c,mm:f,h:c,hh:f,d:c,dd:f,M:c,MM:f,y:c,yy:f},ordinal:function(a){return a+"-oji"},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a.split("_");return c?b%10===1&&11!==b?d[2]:d[3]:b%10===1&&11!==b?d[0]:d[1]}function c(a,c,e){return a+" "+b(d[e],a,c)}var d={mm:"minÅ«ti_minÅ«tes_minÅ«te_minÅ«tes",hh:"stundu_stundas_stunda_stundas",dd:"dienu_dienas_diena_dienas",MM:"mÄ“nesi_mÄ“neÅ¡us_mÄ“nesis_mÄ“neÅ¡i",yy:"gadu_gadus_gads_gadi"};return a.lang("lv",{months:"janvāris_februāris_marts_aprÄ«lis_maijs_jÅ«nijs_jÅ«lijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jÅ«n_jÅ«l_aug_sep_okt_nov_dec".split("_"),weekdays:"svÄ“tdiena_pirmdiena_otrdiena_treÅ¡diena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, LT",LLLL:"YYYY. [gada] D. MMMM, dddd, LT"},calendar:{sameDay:"[Å odien pulksten] LT",nextDay:"[RÄ«t pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"%s vÄ“lāk",past:"%s agrāk",s:"dažas sekundes",m:"minÅ«ti",mm:c,h:"stundu",hh:c,d:"dienu",dd:c,M:"mÄ“nesi",MM:c,y:"gadu",yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Во изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Во изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"после %s",past:"пред %s",s:"неколку секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",M:"месец",MM:"%d месеци",y:"година",yy:"%d години"},ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("ml",{months:"ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ".split("_"),monthsShort:"ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._à´“à´—._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.".split("_"),weekdays:"ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച".split("_"),weekdaysShort:"ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി".split("_"),weekdaysMin:"à´žà´¾_തി_ചൊ_ബു_വ്യാ_വെ_à´¶".split("_"),longDateFormat:{LT:"A h:mm -നു",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[ഇന്ന്] LT",nextDay:"[നാളെ] LT",nextWeek:"dddd, LT",lastDay:"[ഇന്നലെ] LT",lastWeek:"[കഴിഞ്ഞ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s കഴിഞ്ഞ്",past:"%s മുൻപ്",s:"അൽപ നിമിഷങ്ങൾ",m:"ഒരു മിനിറ്റ്",mm:"%d മിനിറ്റ്",h:"ഒരു മണിക്കൂർ",hh:"%d മണിക്കൂർ",d:"ഒരു ദിവസം",dd:"%d ദിവസം",M:"ഒരു മാസം",MM:"%d മാസം",y:"ഒരു വർഷം",yy:"%d വർഷം"},meridiem:function(a){return 4>a?"രാത്രി":12>a?"രാവിലെ":17>a?"ഉച്ച കഴിഞ്ഞ്":20>a?"വൈകുന്നേരം":"രാത്രി"}})}),function(a){a(db)}(function(a){var b={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return a.lang("mr",{months:"जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),monthsShort:"जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),weekdays:"रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm वाजता",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[आज] LT",nextDay:"[उद्या] LT",nextWeek:"dddd, LT",lastDay:"[काल] LT",lastWeek:"[मागील] dddd, LT",sameElse:"L"},relativeTime:{future:"%s नंतर",past:"%s पूर्वी",s:"सेकंद",m:"एक मिनिट",mm:"%d मिनिटे",h:"एक तास",hh:"%d तास",d:"एक दिवस",dd:"%d दिवस",M:"एक महिना",MM:"%d महिने",y:"एक वर्ष",yy:"%d वर्षे"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return b[a]})},meridiem:function(a){return 4>a?"रात्री":10>a?"सकाळी":17>a?"दुपारी":20>a?"सायंकाळी":"रात्री"},week:{dow:0,doy:6}})}),function(a){a(db)}(function(a){return a.lang("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(a){return 11>a?"pagi":15>a?"tengahari":19>a?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"H.mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i gÃ¥r kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en mÃ¥ned",MM:"%d mÃ¥neder",y:"ett Ã¥r",yy:"%d Ã¥r"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){var b={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return a.lang("ne",{months:"जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर".split("_"),monthsShort:"जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.".split("_"),weekdays:"आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार".split("_"),weekdaysShort:"आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.".split("_"),weekdaysMin:"आइ._सो._मङ्_बु._बि._शु._श.".split("_"),longDateFormat:{LT:"Aको h:mm बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return b[a]})},meridiem:function(a){return 3>a?"राती":10>a?"बिहान":15>a?"दिउँसो":18>a?"बेलुका":20>a?"साँझ":"राती"},calendar:{sameDay:"[आज] LT",nextDay:"[भोली] LT",nextWeek:"[आउँदो] dddd[,] LT",lastDay:"[हिजो] LT",lastWeek:"[गएको] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%sमा",past:"%s अगाडी",s:"केही समय",m:"एक मिनेट",mm:"%d मिनेट",h:"एक घण्टा",hh:"%d घण्टा",d:"एक दिन",dd:"%d दिन",M:"एक महिना",MM:"%d महिना",y:"एक बर्ष",yy:"%d बर्ष"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){var b="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),c="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");return a.lang("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(a,d){return/-MMM-/.test(d)?c[a.month()]:b[a.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_mÃ¥ndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_mÃ¥n_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_mÃ¥_ty_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I gÃ¥r klokka] LT",lastWeek:"[FøregÃ¥ende] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekund",m:"ett minutt",mm:"%d minutt",h:"en time",hh:"%d timar",d:"en dag",dd:"%d dagar",M:"en mÃ¥nad",MM:"%d mÃ¥nader",y:"ett Ã¥r",yy:"%d Ã¥r"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function c(a,c,d){var e=a+" ";switch(d){case"m":return c?"minuta":"minutÄ™";case"mm":return e+(b(a)?"minuty":"minut");case"h":return c?"godzina":"godzinÄ™";case"hh":return e+(b(a)?"godziny":"godzin");case"MM":return e+(b(a)?"miesiÄ…ce":"miesiÄ™cy");case"yy":return e+(b(a)?"lata":"lat")}}var d="styczeÅ„_luty_marzec_kwiecieÅ„_maj_czerwiec_lipiec_sierpieÅ„_wrzesieÅ„_październik_listopad_grudzieÅ„".split("_"),e="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_wrzeÅ›nia_października_listopada_grudnia".split("_");return a.lang("pl",{months:function(a,b){return/D MMMM/.test(b)?e[a.month()]:d[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziaÅ‚ek_wtorek_Å›roda_czwartek_piÄ…tek_sobota".split("_"),weekdaysShort:"nie_pon_wt_Å›r_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Åšr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[DziÅ› o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszÅ‚Ä… niedzielÄ™ o] LT";case 3:return"[W zeszÅ‚Ä… Å›rodÄ™ o] LT";case 6:return"[W zeszÅ‚Ä… sobotÄ™ o] LT";default:return"[W zeszÅ‚y] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:c,mm:c,h:c,hh:c,d:"1 dzieÅ„",dd:"%d dni",M:"miesiÄ…c",MM:c,y:"rok",yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje à s] LT",nextDay:"[Amanhã à s] LT",nextWeek:"dddd [à s] LT",lastDay:"[Ontem à s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [à s] LT":"[Última] dddd [à s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%dº"})}),function(a){a(db)}(function(a){return a.lang("pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje à s] LT",nextDay:"[Amanhã à s] LT",nextWeek:"dddd [à s] LT",lastDay:"[Ontem à s] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [à s] LT":"[Última] dddd [à s] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]}return a.lang("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian_feb_mar_apr_mai_iun_iul_aug_sep_oct_noi_dec".split("_"),weekdays:"duminică_luni_marÈ›i_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",m:"un minut",mm:b,h:"o oră",hh:b,d:"o zi",dd:b,M:"o lună",MM:b,y:"un an",yy:b},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mesec":2===a||3===a||4===a?"meseca":"meseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}return a.lang("rs",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[proÅ¡lu] dddd [u] LT";case 6:return"[proÅ¡le] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[proÅ¡li] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"par sekundi",m:b,mm:b,h:b,hh:b,d:"dan",dd:b,M:"mesec",MM:b,y:"godinu",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(a,c,d){var e={mm:"минута_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===d?c?"минута":"минуту":a+" "+b(e[d],+a)}function d(a,b){var c={nominative:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),accusative:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function e(a,b){var c={nominative:"янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),accusative:"янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function f(a,b){var c={nominative:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),accusative:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_")},d=/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/.test(b)?"accusative":"nominative";return c[d][a.day()]}return a.lang("ru",{months:d,monthsShort:e,weekdays:f,weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[й|я]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., LT",LLLL:"dddd, D MMMM YYYY г., LT"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(){return 2===this.day()?"[Во] dddd [в] LT":"[Ð’] dddd [в] LT"},lastWeek:function(){switch(this.day()){case 0:return"[Ð’ прошлое] dddd [в] LT";case 1:case 2:case 4:return"[Ð’ прошлый] dddd [в] LT";case 3:case 5:case 6:return"[Ð’ прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:c,mm:c,h:"час",hh:c,d:"день",dd:c,M:"месяц",MM:c,y:"год",yy:c},meridiem:function(a){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a){return a>1&&5>a}function c(a,c,d,e){var f=a+" ";switch(d){case"s":return c||e?"pár sekúnd":"pár sekundami";case"m":return c?"minúta":e?"minútu":"minútou";case"mm":return c||e?f+(b(a)?"minúty":"minút"):f+"minútami";break;case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(b(a)?"hodiny":"hodín"):f+"hodinami";break;case"d":return c||e?"deň":"dňom";case"dd":return c||e?f+(b(a)?"dni":"dní"):f+"dňami";break;case"M":return c||e?"mesiac":"mesiacom";case"MM":return c||e?f+(b(a)?"mesiace":"mesiacov"):f+"mesiacmi";break;case"y":return c||e?"rok":"rokom";case"yy":return c||e?f+(b(a)?"roky":"rokov"):f+"rokmi"}}var d="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),e="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");return a.lang("sk",{months:d,monthsShort:e,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(d,e),weekdays:"nedeľa_pondelok_utorok_streda_Å¡tvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_Å¡t_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_Å¡t_pi_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo Å¡tvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"ena minuta":"eno minuto";case"mm":return d+=1===a?"minuta":2===a?"minuti":3===a||4===a?"minute":"minut";case"h":return b?"ena ura":"eno uro";case"hh":return d+=1===a?"ura":2===a?"uri":3===a||4===a?"ure":"ur";case"dd":return d+=1===a?"dan":"dni";case"MM":return d+=1===a?"mesec":2===a?"meseca":3===a||4===a?"mesece":"mesecev";case"yy":return d+=1===a?"leto":2===a?"leti":3===a||4===a?"leta":"let"}}return a.lang("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[prejÅ¡nja] dddd [ob] LT";case 1:case 2:case 4:case 5:return"[prejÅ¡nji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"%s nazaj",s:"nekaj sekund",m:b,mm:b,h:b,hh:b,d:"en dan",dd:b,M:"en mesec",MM:b,y:"eno leto",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Marte_E Mërkure_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Neser në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s me parë",s:"disa sekonda",m:"një minut",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_mÃ¥ndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mÃ¥n_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_mÃ¥_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[IgÃ¥r] LT",nextWeek:"dddd LT",lastWeek:"[Förra] dddd[en] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"nÃ¥gra sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en mÃ¥nad",MM:"%d mÃ¥nader",y:"ett Ã¥r",yy:"%d Ã¥r"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":3===b?"e":"e";return a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},ordinal:function(a){return a+"வது" +},meridiem:function(a){return a>=6&&10>=a?" காலை":a>=10&&14>=a?" நண்பகல்":a>=14&&18>=a?" எற்பாடு":a>=18&&20>=a?" மாலை":a>=20&&24>=a?" இரவு":a>=0&&6>=a?" வைகறை":void 0},week:{dow:0,doy:6}})}),function(a){a(db)}(function(a){return a.lang("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),longDateFormat:{LT:"H นาฬิกา m นาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา LT",LLLL:"วันddddที่ D MMMM YYYY เวลา LT"},meridiem:function(a){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}})}),function(a){a(db)}(function(a){return a.lang("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM DD, YYYY LT"},calendar:{sameDay:"[Ngayon sa] LT",nextDay:"[Bukas sa] LT",nextWeek:"dddd [sa] LT",lastDay:"[Kahapon sa] LT",lastWeek:"dddd [huling linggo] LT",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},ordinal:function(a){return a},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){var b={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"};return a.lang("tr",{months:"Ocak_Åžubat_Mart_Nisan_Mayıs_Haziran_Temmuz_AÄŸustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Åžub_Mar_Nis_May_Haz_Tem_AÄŸu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_ÇarÅŸamba_PerÅŸembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinal:function(a){if(0===a)return a+"'ıncı";var c=a%10,d=a%100-c,e=a>=100?100:null;return a+(b[c]||b[d]||b[e])},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("tzm-la",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_É£wÅ¡t_Å¡wtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_É£wÅ¡t_Å¡wtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",m:"minuḍ",mm:"%d minuḍ",h:"saÉ›a",hh:"%d tassaÉ›in",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){return a.lang("tzm",{months:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),monthsShort:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),weekdays:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysShort:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysMin:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[ⴰⵙⴷⵅ â´´] LT",nextDay:"[ⴰⵙⴽⴰ â´´] LT",nextWeek:"dddd [â´´] LT",lastDay:"[ⴰⵚⴰⵏⵜ â´´] LT",lastWeek:"dddd [â´´] LT",sameElse:"L"},relativeTime:{future:"â´·â´°â´·âµ… âµ™ ⵢⴰⵏ %s",past:"ⵢⴰⵏ %s",s:"ⵉⵎⵉⴽ",m:"ⵎⵉⵏⵓⴺ",mm:"%d ⵎⵉⵏⵓⴺ",h:"ⵙⴰⵄⴰ",hh:"%d ⵜⴰⵙⵙⴰⵄⵉⵏ",d:"ⴰⵙⵙ",dd:"%d oⵙⵙⴰⵏ",M:"â´°âµ¢oⵓⵔ",MM:"%d ⵉⵢⵢⵉⵔⵏ",y:"ⴰⵙⴳⴰⵙ",yy:"%d ⵉⵙⴳⴰⵙⵏ"},week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){function b(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(a,c,d){var e={mm:"хвилина_хвилини_хвилин",hh:"година_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===d?c?"хвилина":"хвилину":"h"===d?c?"година":"годину":a+" "+b(e[d],+a)}function d(a,b){var c={nominative:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_"),accusative:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_")},d=/D[oD]? *MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function e(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")},d=/(\[[ВвУу]\]) ?dddd/.test(b)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(b)?"genitive":"nominative";return c[d][a.day()]}function f(a){return function(){return a+"о"+(11===this.hours()?"б":"")+"] LT"}}return a.lang("uk",{months:d,monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:e,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY Ñ€.",LLL:"D MMMM YYYY Ñ€., LT",LLLL:"dddd, D MMMM YYYY Ñ€., LT"},calendar:{sameDay:f("[Сьогодні "),nextDay:f("[Завтра "),lastDay:f("[Вчора "),nextWeek:f("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return f("[Минулої] dddd [").call(this);case 1:case 2:case 4:return f("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",m:c,mm:c,h:"годину",hh:c,d:"день",dd:c,M:"місяць",MM:c,y:"рік",yy:c},meridiem:function(a){return 4>a?"ночі":12>a?"ранку":17>a?"дня":"вечора"},ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a+"-й";case"D":return a+"-го";default:return a}},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("uz",{months:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),weekdaysShort:"Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),weekdaysMin:"Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"D MMMM YYYY, dddd LT"},calendar:{sameDay:"[Бугун соат] LT [да]",nextDay:"[Эртага] LT [да]",nextWeek:"dddd [куни соат] LT [да]",lastDay:"[Кеча соат] LT [да]",lastWeek:"[Утган] dddd [куни соат] LT [да]",sameElse:"L"},relativeTime:{future:"Якин %s ичида",past:"Бир неча %s олдин",s:"фурсат",m:"бир дакика",mm:"%d дакика",h:"бир соат",hh:"%d соат",d:"бир кун",dd:"%d кун",M:"бир ой",MM:"%d ой",y:"бир йил",yy:"%d йил"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("vn",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),weekdays:"chủ nhật_thứ hai_thứ ba_thứ tÆ°_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY LT",LLLL:"dddd, D MMMM [năm] YYYY LT",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY LT",llll:"ddd, D MMM YYYY LT"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngà y mai lúc] LT",nextWeek:"dddd [tuần tá»›i lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tá»›i",past:"%s trÆ°á»›c",s:"và i giây",m:"má»™t phút",mm:"%d phút",h:"má»™t giờ",hh:"%d giờ",d:"má»™t ngà y",dd:"%d ngà y",M:"má»™t tháng",MM:"%d tháng",y:"má»™t năm",yy:"%d năm"},ordinal:function(a){return a},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"æ—¥_一_二_三_å››_五_å…­".split("_"),longDateFormat:{LT:"Ah点mm",L:"YYYY-MM-DD",LL:"YYYYå¹´MMMDæ—¥",LLL:"YYYYå¹´MMMDæ—¥LT",LLLL:"YYYYå¹´MMMDæ—¥ddddLT",l:"YYYY-MM-DD",ll:"YYYYå¹´MMMDæ—¥",lll:"YYYYå¹´MMMDæ—¥LT",llll:"YYYYå¹´MMMDæ—¥ddddLT"},meridiem:function(a,b){var c=100*a+b;return 600>c?"凌晨":900>c?"早上":1130>c?"上午":1230>c?"中午":1800>c?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var b,c;return b=a().startOf("week"),c=this.unix()-b.unix()>=604800?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var b,c;return b=a().startOf("week"),c=this.unix()c?"早上":1130>c?"上午":1230>c?"中午":1800>c?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"æ—¥";case"M":return a+"月";case"w":case"W":return a+"週";default:return a}},relativeTime:{future:"%så…§",past:"%s前",s:"幾秒",m:"一分鐘",mm:"%d分鐘",h:"一小時",hh:"%d小時",d:"一天",dd:"%d天",M:"一個月",MM:"%d個月",y:"一年",yy:"%då¹´"}})}),db.lang("en"),rb?(module.exports=db,cb(!0)):"function"==typeof define&&define.amd?define("moment",function(b,c,d){return d.config&&d.config()&&d.config().noGlobal!==!0&&cb(d.config().noGlobal===a),db}):cb()}).call(this); diff --git a/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.css b/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.css index da12d98330..094315a43c 100644 --- a/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.css +++ b/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.css @@ -1,11 +1,12 @@ +/* css for timepicker */ .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } .ui-timepicker-div dl { text-align: left; } .ui-timepicker-div dl dt { float: left; clear:left; padding: 0 0 0 5px; } -.ui-timepicker-div dl dd { margin: 0 10px 10px 40%; } +.ui-timepicker-div dl dd { margin: 0 10px 10px 45%; } .ui-timepicker-div td { font-size: 90%; } .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; } .ui-timepicker-rtl{ direction: rtl; } .ui-timepicker-rtl dl { text-align: right; padding: 0 5px 0 0; } .ui-timepicker-rtl dl dt{ float: right; clear: right; } -.ui-timepicker-rtl dl dd { margin: 0 40% 10px 10px; } \ No newline at end of file +.ui-timepicker-rtl dl dd { margin: 0 45% 10px 10px; } diff --git a/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.js b/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.js index 71ec2cda62..ef271950fd 100644 --- a/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.js +++ b/main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.js @@ -1,2151 +1,2197 @@ -/* - * jQuery Timepicker Addon - * By: Trent Richardson [http://trentrichardson.com] - * - * Copyright 2013 Trent Richardson - * You may use this project under MIT license. - * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt - */ - +/*! jQuery Timepicker Addon - v1.4.4 - 2014-03-29 + * http://trentrichardson.com/examples/timepicker + * Copyright (c) 2014 Trent Richardson; Licensed MIT */ (function ($) { - /* - * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded" - */ - $.ui.timepicker = $.ui.timepicker || {}; - if ($.ui.timepicker.version) { - return; - } - - /* - * Extend jQueryUI, get it started with our version number - */ - $.extend($.ui, { - timepicker: { - version: "@@version" - } - }); - - /* - * Timepicker manager. - * Use the singleton instance of this class, $.timepicker, to interact with the time picker. - * Settings for (groups of) time pickers are maintained in an instance object, - * allowing multiple different settings on the same page. - */ - var Timepicker = function () { - this.regional = []; // Available regional settings, indexed by language code - this.regional[''] = { // Default regional settings - currentText: 'Now', - closeText: 'Done', - amNames: ['AM', 'A'], - pmNames: ['PM', 'P'], - timeFormat: 'HH:mm', - timeSuffix: '', - timeOnlyTitle: 'Choose Time', - timeText: 'Time', - hourText: 'Hour', - minuteText: 'Minute', - secondText: 'Second', - millisecText: 'Millisecond', - microsecText: 'Microsecond', - timezoneText: 'Time Zone', - isRTL: false - }; - this._defaults = { // Global defaults for all the datetime picker instances - showButtonPanel: true, - timeOnly: false, - showHour: null, - showMinute: null, - showSecond: null, - showMillisec: null, - showMicrosec: null, - showTimezone: null, - showTime: true, - stepHour: 1, - stepMinute: 1, - stepSecond: 1, - stepMillisec: 1, - stepMicrosec: 1, - hour: 0, - minute: 0, - second: 0, - millisec: 0, - microsec: 0, - timezone: null, - hourMin: 0, - minuteMin: 0, - secondMin: 0, - millisecMin: 0, - microsecMin: 0, - hourMax: 23, - minuteMax: 59, - secondMax: 59, - millisecMax: 999, - microsecMax: 999, - minDateTime: null, - maxDateTime: null, - onSelect: null, - hourGrid: 0, - minuteGrid: 0, - secondGrid: 0, - millisecGrid: 0, - microsecGrid: 0, - alwaysSetTime: true, - separator: ' ', - altFieldTimeOnly: true, - altTimeFormat: null, - altSeparator: null, - altTimeSuffix: null, - pickerTimeFormat: null, - pickerTimeSuffix: null, - showTimepicker: true, - timezoneList: null, - addSliderAccess: false, - sliderAccessArgs: null, - controlType: 'slider', - defaultValue: null, - parse: 'strict' - }; - $.extend(this._defaults, this.regional['']); - }; - - $.extend(Timepicker.prototype, { - $input: null, - $altInput: null, - $timeObj: null, - inst: null, - hour_slider: null, - minute_slider: null, - second_slider: null, - millisec_slider: null, - microsec_slider: null, - timezone_select: null, - hour: 0, - minute: 0, - second: 0, - millisec: 0, - microsec: 0, - timezone: null, - hourMinOriginal: null, - minuteMinOriginal: null, - secondMinOriginal: null, - millisecMinOriginal: null, - microsecMinOriginal: null, - hourMaxOriginal: null, - minuteMaxOriginal: null, - secondMaxOriginal: null, - millisecMaxOriginal: null, - microsecMaxOriginal: null, - ampm: '', - formattedDate: '', - formattedTime: '', - formattedDateTime: '', - timezoneList: null, - units: ['hour', 'minute', 'second', 'millisec', 'microsec'], - support: {}, - control: null, - - /* - * Override the default settings for all instances of the time picker. - * @param {Object} settings object - the new settings to use as defaults (anonymous object) - * @return {Object} the manager object - */ - setDefaults: function (settings) { - extendRemove(this._defaults, settings || {}); - return this; - }, - - /* - * Create a new Timepicker instance - */ - _newInst: function ($input, opts) { - var tp_inst = new Timepicker(), - inlineSettings = {}, - fns = {}, - overrides, i; - - for (var attrName in this._defaults) { - if (this._defaults.hasOwnProperty(attrName)) { - var attrValue = $input.attr('time:' + attrName); - if (attrValue) { - try { - inlineSettings[attrName] = eval(attrValue); - } catch (err) { - inlineSettings[attrName] = attrValue; - } - } - } - } - - overrides = { - beforeShow: function (input, dp_inst) { - if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) { - return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst); - } - }, - onChangeMonthYear: function (year, month, dp_inst) { - // Update the time as well : this prevents the time from disappearing from the $input field. - tp_inst._updateDateTime(dp_inst); - if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) { - tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); - } - }, - onClose: function (dateText, dp_inst) { - if (tp_inst.timeDefined === true && $input.val() !== '') { - tp_inst._updateDateTime(dp_inst); - } - if ($.isFunction(tp_inst._defaults.evnts.onClose)) { - tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst); - } - } - }; - for (i in overrides) { - if (overrides.hasOwnProperty(i)) { - fns[i] = opts[i] || null; - } - } - - tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, { - evnts: fns, - timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); - }); - tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) { - return val.toUpperCase(); - }); - tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) { - return val.toUpperCase(); - }); - - // detect which units are supported - tp_inst.support = detectSupport( - tp_inst._defaults.timeFormat + - (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') + - (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : '')); - - // controlType is string - key to our this._controls - if (typeof(tp_inst._defaults.controlType) === 'string') { - if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') { - tp_inst._defaults.controlType = 'select'; - } - tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType]; - } - // controlType is an object and must implement create, options, value methods - else { - tp_inst.control = tp_inst._defaults.controlType; - } - - // prep the timezone options - var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60, - 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840]; - if (tp_inst._defaults.timezoneList !== null) { - timezoneList = tp_inst._defaults.timezoneList; - } - var tzl = timezoneList.length, tzi = 0, tzv = null; - if (tzl > 0 && typeof timezoneList[0] !== 'object') { - for (; tzi < tzl; tzi++) { - tzv = timezoneList[tzi]; - timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) }; - } - } - tp_inst._defaults.timezoneList = timezoneList; - - // set the default units - tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) : - ((new Date()).getTimezoneOffset() * -1); - tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin : - tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour; - tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin : - tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute; - tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin : - tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second; - tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin : - tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec; - tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin : - tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec; - tp_inst.ampm = ''; - tp_inst.$input = $input; - - if (tp_inst._defaults.altField) { - tp_inst.$altInput = $(tp_inst._defaults.altField).css({ - cursor: 'pointer' - }).focus(function () { - $input.trigger("focus"); - }); - } - - if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) { - tp_inst._defaults.minDate = new Date(); - } - if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) { - tp_inst._defaults.maxDate = new Date(); - } - - // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. - if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) { - tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); - } - if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) { - tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); - } - if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) { - tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); - } - if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) { - tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); - } - tp_inst.$input.bind('focus', function () { - tp_inst._onFocus(); - }); - - return tp_inst; - }, - - /* - * add our sliders to the calendar - */ - _addTimePicker: function (dp_inst) { - var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val(); - - this.timeDefined = this._parseTime(currDT); - this._limitMinMaxDateTime(dp_inst, false); - this._injectTimePicker(); - }, - - /* - * parse the time string from input value or _setTime - */ - _parseTime: function (timeString, withDate) { - if (!this.inst) { - this.inst = $.datepicker._getInst(this.$input[0]); - } - - if (withDate || !this._defaults.timeOnly) { - var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); - try { - var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults); - if (!parseRes.timeObj) { - return false; - } - $.extend(this, parseRes.timeObj); - } catch (err) { - $.timepicker.log("Error parsing the date/time string: " + err + - "\ndate/time string = " + timeString + - "\ntimeFormat = " + this._defaults.timeFormat + - "\ndateFormat = " + dp_dateFormat); - return false; - } - return true; - } else { - var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults); - if (!timeObj) { - return false; - } - $.extend(this, timeObj); - return true; - } - }, - - /* - * generate and inject html for timepicker into ui datepicker - */ - _injectTimePicker: function () { - var $dp = this.inst.dpDiv, - o = this.inst.settings, - tp_inst = this, - litem = '', - uitem = '', - show = null, - max = {}, - gridSize = {}, - size = null, - i = 0, - l = 0; - - // Prevent displaying twice - if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) { - var noDisplay = ' style="display:none;"', - html = '
' + '
' + o.timeText + '
' + - '
'; - - // Create the markup - for (i = 0, l = this.units.length; i < l; i++) { - litem = this.units[i]; - uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1); - show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem]; - - // Added by Peter Medeiros: - // - Figure out what the hour/minute/second max should be based on the step values. - // - Example: if stepMinute is 15, then minMax is 45. - max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10); - gridSize[litem] = 0; - - html += '
' + o[litem + 'Text'] + '
' + - '
'; - - if (show && o[litem + 'Grid'] > 0) { - html += '
'; - - if (litem === 'hour') { - for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) { - gridSize[litem]++; - var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o); - html += ''; - } - } - else { - for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) { - gridSize[litem]++; - html += ''; - } - } - - html += '
' + tmph + '' + ((m < 10) ? '0' : '') + m + '
'; - } - html += '
'; - } - - // Timezone - var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone; - html += '
' + o.timezoneText + '
'; - html += '
'; - - // Create the elements from string - html += '
'; - var $tp = $(html); - - // if we only want time picker... - if (o.timeOnly === true) { - $tp.prepend('
' + '
' + o.timeOnlyTitle + '
' + '
'); - $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide(); - } - - // add sliders, adjust grids, add events - for (i = 0, l = tp_inst.units.length; i < l; i++) { - litem = tp_inst.units[i]; - uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1); - show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem]; - - // add the slider - tp_inst[litem + '_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_' + litem + '_slider'), litem, tp_inst[litem], o[litem + 'Min'], max[litem], o['step' + uitem]); - - // adjust the grid and add click event - if (show && o[litem + 'Grid'] > 0) { - size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']); - $tp.find('.ui_tpicker_' + litem + ' table').css({ - width: size + "%", - marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"), - marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0', - borderCollapse: 'collapse' - }).find("td").click(function (e) { - var $t = $(this), - h = $t.html(), - n = parseInt(h.replace(/[^0-9]/g), 10), - ap = h.replace(/[^apm]/ig), - f = $t.data('for'); // loses scope, so we use data-for - - if (f === 'hour') { - if (ap.indexOf('p') !== -1 && n < 12) { - n += 12; - } - else { - if (ap.indexOf('a') !== -1 && n === 12) { - n = 0; - } - } - } - - tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n); - - tp_inst._onTimeChange(); - tp_inst._onSelectHandler(); - }).css({ - cursor: 'pointer', - width: (100 / gridSize[litem]) + '%', - textAlign: 'center', - overflow: 'hidden' - }); - } // end if grid > 0 - } // end for loop - - // Add timezone options - this.timezone_select = $tp.find('.ui_tpicker_timezone').append('').find("select"); - $.fn.append.apply(this.timezone_select, - $.map(o.timezoneList, function (val, idx) { - return $("\n"; } - - foreach ($this->_optgroups as $optgroup) { - $strHtml .= $tabs . "\t"; - - foreach($optgroup['options'] as $option) { - $strHtml .= $tabs . "\t_getAttrString($option['attr']) . '>' . - $option['text'] . "\n"; + foreach ($this->_optgroups as $optgroup) { + $strHtml .= $tabs . ""; + foreach ($optgroup['options'] as $option) { + $text = $option['text']; + unset($option['text']); + $strHtml .= $tabs . " _getAttrString($option) . '>' .$text . ""; } - - $strHtml .= "\n"; + $strHtml .= ""; } return $strHtml . $tabs . ''; } - } //end func toHtml + } - // }}} - // {{{ getFrozenHtml() /** * Returns the value of field without HTML tags diff --git a/main/template/default/agenda/event_list.tpl b/main/template/default/agenda/event_list.tpl index 264218c44c..672cbb9d34 100644 --- a/main/template/default/agenda/event_list.tpl +++ b/main/template/default/agenda/event_list.tpl @@ -18,19 +18,19 @@ {% for event in agenda_events %} - {{ event.start |date("m/d/Y h:i:s") }} + {{ event.start_date_localtime }} {% if event.allDay %} {{ 'AllDay' | get_lang }} {% else %} - {{ event.end |date("m/d/Y h:i:s") }} + {{ event.end_date_localtime }} {% endif %} {{ event.title }}

{{ event.description}}

- + {{ event.attachment }} {% if is_allowed_to_edit %} diff --git a/main/template/default/agenda/month.tpl b/main/template/default/agenda/month.tpl index 7e4d22c57e..5a658a726a 100644 --- a/main/template/default/agenda/month.tpl +++ b/main/template/default/agenda/month.tpl @@ -166,13 +166,11 @@ $(document).ready(function() { $('#color_calendar').addClass('label_tag'); $('#color_calendar').addClass('{{ type_event_class }}'); - allFields.removeClass( "ui-state-error" ); - + allFields.removeClass("ui-state-error"); $("#dialog-form").dialog("open"); - $("#dialog-form").dialog({ buttons: { - '{{ "Add"|get_lang}}' : function() { + '{{ "Add" | get_lang }}' : function() { var bValid = true; bValid = bValid && checkLength( title, "title", 1, 255 ); //bValid = bValid && checkLength( content, "content", 1, 255 ); @@ -183,7 +181,6 @@ $(document).ready(function() { success:function(data) { var user = $('#users_to_send_id').val(); if (user) { - if (user.length > 1) { user = 0; } else { @@ -192,7 +189,7 @@ $(document).ready(function() { var user_length = String(user).length; if (String(user).substring(0,1) == 'G') { var user_id = String(user).substring(6,user_length); - var user_id = "G:"+user_id; + var user_id = "G:"+user_id; } else { var user_id = String(user).substring(5,user_length); } @@ -201,17 +198,20 @@ $(document).ready(function() { var url_length = String(window.location).length; var url = String(window.location).substring(0, position)+temp; - if (position > 0) { + /*if (position > 0) { window.location.replace(url); } else { url = String(window.location)+temp; window.location.replace(url); - } + }*/ } else { - calendar.fullCalendar("refetchEvents"); - calendar.fullCalendar("rerenderEvents"); + /* calendar.fullCalendar("refetchEvents"); + calendar.fullCalendar("rerenderEvents");*/ } + calendar.fullCalendar("refetchEvents"); + calendar.fullCalendar("rerenderEvents"); + $("#dialog-form").dialog("close"); } }); @@ -222,8 +222,10 @@ $(document).ready(function() { $("#content").attr('value', ''); } }); - //Don't follow the link + + // Don't follow the link. return false; + calendar.fullCalendar('unselect'); //Reload events calendar.fullCalendar("refetchEvents"); @@ -307,27 +309,25 @@ $(document).ready(function() { $("#dialog-form").dialog("open"); - var url = '{{web_agenda_ajax_url}}&a=edit_event&id='+calEvent.id+'&start='+start_date+'&end='+end_date+'&all_day='+calEvent.allDay+'&view='+view.name; - var delete_url = '{{web_agenda_ajax_url}}&a=delete_event&id='+calEvent.id; + var url = '{{ web_agenda_ajax_url }}&a=edit_event&id='+calEvent.id+'&start='+start_date+'&end='+end_date+'&all_day='+calEvent.allDay+'&view='+view.name; + var delete_url = '{{ web_agenda_ajax_url }}&a=delete_event&id='+calEvent.id; $("#dialog-form").dialog({ buttons: { '{{ "ExportiCalConfidential"|get_lang }}' : function() { - url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=confidential"; + url = "{{ _p.web_main }}calendar/ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=confidential"; window.location.href = url; }, '{{ "ExportiCalPrivate"|get_lang }}': function() { - url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=private"; + url = "{{ _p.web_main }}calendar/ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=private"; window.location.href = url; }, '{{ "ExportiCalPublic"|get_lang }}': function() { - url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=public"; + url = "{{ _p.web_main }}calendar/ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=public"; window.location.href = url; }, - {% if type == 'not_available' %} - '{{ "Edit"|get_lang }}' : function() { - + '{{ "Edit" | get_lang }}' : function() { var bValid = true; bValid = bValid && checkLength( title, "title", 1, 255 ); @@ -352,12 +352,67 @@ $(document).ready(function() { {% endif %} '{{ "Edit"|get_lang }}' : function() { - url = "agenda.php?action=edit&type=fromjs&id=" + calEvent.id+'&course_id='+calEvent.course_id+""; + url = "{{ _p.web_main }}calendar/agenda.php?action=edit&type=fromjs&id=" + calEvent.id+'&course_id='+calEvent.course_id+""; window.location.href = url; $("#dialog-form").dialog( "close" ); }, '{{ "Delete"|get_lang }}': function() { + + if (calEvent.parent_event_id || calEvent.has_children != '' ) { + var newDiv = $(document.createElement('div')); + //newDiv.html('{{ "" |get_lang }}'); + + newDiv.dialog({ + modal: true, + title: "{{ 'Confirmation' | get_lang }}" + }); + + var buttons = newDiv.dialog("option", "buttons"); + + if (calEvent.has_children == '0') { + $.extend(buttons, { + '{{ "DeleteThisItem" | get_lang }}' : function() { + $.ajax({ + url: delete_url, + success:function() { + calendar.fullCalendar('removeEvents', + calEvent + ); + calendar.fullCalendar("refetchEvents"); + calendar.fullCalendar("rerenderEvents"); + $("#dialog-form").dialog( "close" ); + newDiv.dialog( "close" ); + } + }); + } + }); + newDiv.dialog("option", "buttons", buttons); + } + + var buttons = newDiv.dialog("option", "buttons"); + + $.extend(buttons, { + '{{ "DeleteAllItems" | get_lang }}' : function() { + $.ajax({ + url: delete_url+'&delete_all_events=1', + success:function() { + calendar.fullCalendar('removeEvents', + calEvent + ); + calendar.fullCalendar("refetchEvents"); + calendar.fullCalendar("rerenderEvents"); + $("#dialog-form").dialog( "close" ); + newDiv.dialog( "close" ); + } + }); + } + }); + newDiv.dialog("option", "buttons", buttons); + + return true; + } + $.ajax({ url: delete_url, success:function() { @@ -399,32 +454,30 @@ $(document).ready(function() { $("#simple_title").html(calEvent.title); $("#simple_content").html(calEvent.description); $("#simple-dialog-form").dialog("open"); - $("#simple-dialog-form").dialog({ buttons: { '{{"ExportiCalConfidential"|get_lang}}' : function() { - url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=confidential"; - window.location.href = url; + url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=confidential"; + window.location.href = url; }, '{{"ExportiCalPrivate"|get_lang}}': function() { - url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=private"; - window.location.href = url; + url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=private"; + window.location.href = url; }, '{{"ExportiCalPublic"|get_lang}}': function() { - url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=public"; - window.location.href = url; + url = "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=public"; + window.location.href = url; } } }); - } }, editable: true, events: "{{web_agenda_ajax_url}}&a=get_events", eventDrop: function(event, day_delta, minute_delta, all_day, revert_func) { $.ajax({ - url: '{{web_agenda_ajax_url}}', + url: '{{ web_agenda_ajax_url }}', data: { a:'move_event', id: event.id, day_delta: day_delta, minute_delta: minute_delta } @@ -432,7 +485,7 @@ $(document).ready(function() { }, eventResize: function(event, day_delta, minute_delta, revert_func) { $.ajax({ - url: '{{web_agenda_ajax_url}}', + url: '{{ web_agenda_ajax_url }}', data: { a:'resize_event', id: event.id, day_delta: day_delta, minute_delta: minute_delta } @@ -447,25 +500,26 @@ $(document).ready(function() { }); }); +{{ actions_div }} '); $form->addElement('checkbox', 'enableEndDate', null, get_lang('EnableEndDate'), 'id="end_date"'); @@ -3794,7 +3808,7 @@ function getFormWork($form, $defaults = array()) $form->addElement('html', ''); $form->addElement('checkbox', 'add_to_calendar', null, get_lang('AddToCalendar')); diff --git a/plugin/bbb/listing.php b/plugin/bbb/listing.php index 265d06786e..7caef53be0 100644 --- a/plugin/bbb/listing.php +++ b/plugin/bbb/listing.php @@ -32,7 +32,14 @@ if ($teacher) { $title = sprintf(get_lang('VideoConferenceXCourseX'), $id, $course_info['name']); $content = Display::url(get_lang('GoToTheVideoConference'), $_GET['url']); - $event_id = $agenda->add_event($_REQUEST['start'], null, 'true', null, $title, $content, array('everyone')); + $event_id = $agenda->add_event( + $_REQUEST['start'], + null, + 'true', + $title, + $content, + array('everyone') + ); if (!empty($event_id)) { $message = Display::return_message(get_lang('VideoConferenceAddedToTheCalendar'), 'success'); } else { diff --git a/plugin/openmeetings/listing.php b/plugin/openmeetings/listing.php index 4bd0ba0f79..ef148c2709 100644 --- a/plugin/openmeetings/listing.php +++ b/plugin/openmeetings/listing.php @@ -31,7 +31,14 @@ if ($teacher) { $title = sprintf(get_lang('VideoConferenceXCourseX'), $id, $course_info['name']); $content = Display::url(get_lang('GoToTheVideoConference'), $_GET['url']); - $event_id = $agenda->add_event($_REQUEST['start'], null, 'true', null, $title, $content, array('everyone')); + $event_id = $agenda->add_event( + $_REQUEST['start'], + null, + 'true', + $title, + $content, + array('everyone') + ); if (!empty($event_id)) { $message = Display::return_message(get_lang('VideoConferenceAddedToTheCalendar'), 'success'); } else { diff --git a/tests/main/admin/calendar.lib.test.php b/tests/main/admin/calendar.lib.test.php index 7a4f575ca8..760a0723d6 100755 --- a/tests/main/admin/calendar.lib.test.php +++ b/tests/main/admin/calendar.lib.test.php @@ -354,18 +354,6 @@ class TestCalendar extends UnitTestCase { $this->assertTrue(is_null($res)); } - public function testGetAgendaitems(){ - global $_user; - global $_configuration; - $month=01; - $year=2010; - $res = get_agendaitems($month, $year); - if(is_array($res)) { - $this->assertTrue(is_array($res)); - } - - } - public function testDisplayUpcomingEvents(){ ob_start(); $res = display_upcoming_events(); @@ -376,6 +364,4 @@ class TestCalendar extends UnitTestCase { public function testIsRepeatedEvent() { //This is deprecated or not used } - } -?> diff --git a/vendor/autoload.php b/vendor/autoload.php index 416086e080..c9951c8283 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit66dd73b468c5607bacc52774d2bd8959::getLoader(); +return ComposerAutoloaderInitc8544b9da483382b715efa095e59273d::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index f438e319cd..a710555314 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -266,7 +266,7 @@ class ClassLoader public function loadClass($class) { if ($file = $this->findFile($class)) { - include $file; + includeFile($file); return true; } @@ -291,8 +291,25 @@ class ClassLoader return $this->classMap[$class]; } + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { @@ -321,7 +338,7 @@ class ClassLoader . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php'; + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; } if (isset($this->prefixesPsr0[$first])) { @@ -347,8 +364,15 @@ class ClassLoader if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { return $file; } - - // Remember that this class does not exist. - return $this->classMap[$class] = false; } } + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index 60c7c25c46..c36d513df1 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -8,9 +8,9 @@ $baseDir = dirname($vendorDir); return array( 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), + 'Sabre\\VObject' => array($vendorDir . '/sabre/vobject/lib'), 'Psr\\Log\\' => array($vendorDir . '/psr/log'), 'Neutron' => array($vendorDir . '/neutron/temporary-filesystem/src'), - 'Monolog' => array($vendorDir . '/monolog/monolog/src'), 'FFMpeg' => array($vendorDir . '/php-ffmpeg/php-ffmpeg/src'), 'Evenement' => array($vendorDir . '/evenement/evenement/src'), 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 1577e0b28f..4779c3a585 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit66dd73b468c5607bacc52774d2bd8959 +class ComposerAutoloaderInitc8544b9da483382b715efa095e59273d { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInit66dd73b468c5607bacc52774d2bd8959 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit66dd73b468c5607bacc52774d2bd8959', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitc8544b9da483382b715efa095e59273d', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit66dd73b468c5607bacc52774d2bd8959', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitc8544b9da483382b715efa095e59273d', 'loadClassLoader')); $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); @@ -46,3 +46,8 @@ class ComposerAutoloaderInit66dd73b468c5607bacc52774d2bd8959 return $loader; } } + +function composerRequirec8544b9da483382b715efa095e59273d($file) +{ + require $file; +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 4c848866ff..7256e201b9 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,28 +1,34 @@ [ { - "name": "evenement/evenement", - "version": "v1.0.0", - "version_normalized": "1.0.0.0", + "name": "symfony/filesystem", + "version": "v2.4.3", + "version_normalized": "2.4.3.0", + "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", - "url": "https://github.com/igorw/evenement.git", - "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d" + "url": "https://github.com/symfony/Filesystem.git", + "reference": "b717952487176a993e9b12a08b87beae25ae419c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/fa966683e7df3e5dd5929d984a44abfbd6bafe8d", - "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/b717952487176a993e9b12a08b87beae25ae419c", + "reference": "b717952487176a993e9b12a08b87beae25ae419c", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.3" }, - "time": "2012-05-30 15:01:08", + "time": "2014-03-26 11:55:03", "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, "installation-source": "dist", "autoload": { "psr-0": { - "Evenement": "src" + "Symfony\\Component\\Filesystem\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -31,47 +37,46 @@ ], "authors": [ { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch", - "homepage": "http://wiedler.ch/igor/" + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" } ], - "description": "Événement is a very simple event dispatching library for PHP 5.3", - "keywords": [ - "event-dispatcher" - ] + "description": "Symfony Filesystem Component", + "homepage": "http://symfony.com" }, { - "name": "alchemy/binary-driver", - "version": "1.5.0", - "version_normalized": "1.5.0.0", + "name": "neutron/temporary-filesystem", + "version": "2.1.1", + "version_normalized": "2.1.1.0", "source": { "type": "git", - "url": "https://github.com/alchemy-fr/BinaryDriver.git", - "reference": "b32c03d4b56ce29f783051eac55887adae654b41" + "url": "https://github.com/romainneutron/Temporary-Filesystem.git", + "reference": "6b21fa99fd452efea16b9a7adb7304ccfff854d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/BinaryDriver/zipball/b32c03d4b56ce29f783051eac55887adae654b41", - "reference": "b32c03d4b56ce29f783051eac55887adae654b41", + "url": "https://api.github.com/repos/romainneutron/Temporary-Filesystem/zipball/6b21fa99fd452efea16b9a7adb7304ccfff854d0", + "reference": "6b21fa99fd452efea16b9a7adb7304ccfff854d0", "shasum": "" }, "require": { - "evenement/evenement": "~1.0", - "monolog/monolog": "~1.3", - "php": ">=5.3.3", - "psr/log": "~1.0", - "symfony/process": "~2.0" + "symfony/filesystem": "~2.0" }, "require-dev": { "phpunit/phpunit": "~3.7" }, - "time": "2013-06-21 15:51:20", + "time": "2013-10-10 10:58:09", "type": "library", "installation-source": "dist", "autoload": { "psr-0": { - "Alchemy": "src" + "Neutron": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -83,64 +88,34 @@ "name": "Romain Neutron", "email": "imprec@gmail.com", "homepage": "http://www.lickmychip.com/" - }, - { - "name": "Nicolas Le Goff", - "email": "legoff.n@gmail.com" - }, - { - "name": "Phraseanet Team", - "email": "info@alchemy.fr", - "homepage": "http://www.phraseanet.com/" } ], - "description": "A set of tools to build binary drivers", - "keywords": [ - "binary", - "driver" - ] + "description": "Symfony filesystem extension to handle temporary files" }, { - "name": "php-ffmpeg/php-ffmpeg", - "version": "0.3.x-dev", - "version_normalized": "0.3.9999999.9999999-dev", + "name": "evenement/evenement", + "version": "v1.0.0", + "version_normalized": "1.0.0.0", "source": { "type": "git", - "url": "https://github.com/alchemy-fr/PHP-FFmpeg.git", - "reference": "185fb5c33da594db7ffbf3f89d48e9841bc666a0" + "url": "https://github.com/igorw/evenement.git", + "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/PHP-FFmpeg/zipball/185fb5c33da594db7ffbf3f89d48e9841bc666a0", - "reference": "185fb5c33da594db7ffbf3f89d48e9841bc666a0", + "url": "https://api.github.com/repos/igorw/evenement/zipball/fa966683e7df3e5dd5929d984a44abfbd6bafe8d", + "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d", "shasum": "" }, "require": { - "alchemy/binary-driver": "~1.5", - "doctrine/cache": "~1.0", - "evenement/evenement": "~1.0", - "neutron/temporary-filesystem": "~2.1, >=2.1.1", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~3.7", - "sami/sami": "~1.0", - "silex/silex": "~1.0" - }, - "suggest": { - "php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg" + "php": ">=5.3.0" }, - "time": "2013-10-21 12:13:46", + "time": "2012-05-30 15:01:08", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.4-dev" - } - }, - "installation-source": "source", + "installation-source": "dist", "autoload": { "psr-0": { - "FFMpeg": "src" + "Evenement": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -149,26 +124,14 @@ ], "authors": [ { - "name": "Romain Neutron", - "email": "imprec@gmail.com", - "homepage": "http://www.lickmychip.com/" - }, - { - "name": "Phraseanet Team", - "email": "info@alchemy.fr", - "homepage": "http://www.phraseanet.com/" + "name": "Igor Wiedler", + "email": "igor@wiedler.ch", + "homepage": "http://wiedler.ch/igor/" } ], - "description": "FFMpeg PHP, an Object Oriented library to communicate with AVconv / ffmpeg", + "description": "Événement is a very simple event dispatching library for PHP 5.3", "keywords": [ - "audio", - "audio processing", - "avconv", - "avprobe", - "ffmpeg", - "ffprobe", - "video", - "video processing" + "event-dispatcher" ] }, { @@ -215,7 +178,7 @@ ], "authors": [ { - "name": "Jonathan Wage", + "name": "Jonathan H. Wage", "email": "jonwage@gmail.com", "homepage": "http://www.jwage.com/", "role": "Creator" @@ -247,6 +210,57 @@ "caching" ] }, + { + "name": "symfony/process", + "version": "v2.4.3", + "version_normalized": "2.4.3.0", + "target-dir": "Symfony/Component/Process", + "source": { + "type": "git", + "url": "https://github.com/symfony/Process.git", + "reference": "c09c3b08455c35688eee3e481fdfc85518ef01d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Process/zipball/c09c3b08455c35688eee3e481fdfc85518ef01d7", + "reference": "c09c3b08455c35688eee3e481fdfc85518ef01d7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2014-03-26 11:35:33", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Process\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "http://symfony.com" + }, { "name": "psr/log", "version": "1.0.0", @@ -289,17 +303,17 @@ }, { "name": "monolog/monolog", - "version": "1.7.0", - "version_normalized": "1.7.0.0", + "version": "1.8.0", + "version_normalized": "1.8.0.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "6225b22de9dcf36546be3a0b2fa8e3d986153f57" + "reference": "392ef35fd470638e08d0160d6b1cbab63cb23174" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/6225b22de9dcf36546be3a0b2fa8e3d986153f57", - "reference": "6225b22de9dcf36546be3a0b2fa8e3d986153f57", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/392ef35fd470638e08d0160d6b1cbab63cb23174", + "reference": "392ef35fd470638e08d0160d6b1cbab63cb23174", "shasum": "" }, "require": { @@ -307,11 +321,11 @@ "psr/log": "~1.0" }, "require-dev": { - "aws/aws-sdk-php": "~2.4.8", - "doctrine/couchdb": "dev-master", - "mlehner/gelf-php": "1.0.*", + "aws/aws-sdk-php": "~2.4, >2.4.8", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", "phpunit/phpunit": "~3.7.0", - "raven/raven": "0.5.*", + "raven/raven": "~0.5", "ruflin/elastica": "0.90.*" }, "suggest": { @@ -319,21 +333,22 @@ "doctrine/couchdb": "Allow sending log messages to a CouchDB server", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", - "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "raven/raven": "Allow sending log messages to a Sentry server", + "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, - "time": "2013-11-14 19:48:31", + "time": "2014-03-23 19:50:26", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.8.x-dev" } }, "installation-source": "dist", "autoload": { - "psr-0": { - "Monolog": "src/" + "psr-4": { + "Monolog\\": "src/Monolog" } }, "notification-url": "https://packagist.org/downloads/", @@ -357,35 +372,36 @@ ] }, { - "name": "symfony/process", - "version": "v2.4.1", - "version_normalized": "2.4.1.0", - "target-dir": "Symfony/Component/Process", + "name": "alchemy/binary-driver", + "version": "1.5.0", + "version_normalized": "1.5.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/Process.git", - "reference": "58fdccb311e44f28866f976c2d7b3227e9f713db" + "url": "https://github.com/alchemy-fr/BinaryDriver.git", + "reference": "b32c03d4b56ce29f783051eac55887adae654b41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/58fdccb311e44f28866f976c2d7b3227e9f713db", - "reference": "58fdccb311e44f28866f976c2d7b3227e9f713db", + "url": "https://api.github.com/repos/alchemy-fr/BinaryDriver/zipball/b32c03d4b56ce29f783051eac55887adae654b41", + "reference": "b32c03d4b56ce29f783051eac55887adae654b41", "shasum": "" }, "require": { - "php": ">=5.3.3" + "evenement/evenement": "~1.0", + "monolog/monolog": "~1.3", + "php": ">=5.3.3", + "psr/log": "~1.0", + "symfony/process": "~2.0" }, - "time": "2014-01-05 02:10:50", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } + "require-dev": { + "phpunit/phpunit": "~3.7" }, + "time": "2013-06-21 15:51:20", + "type": "library", "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Process\\": "" + "Alchemy": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -394,47 +410,67 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Romain Neutron", + "email": "imprec@gmail.com", + "homepage": "http://www.lickmychip.com/" }, { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Nicolas Le Goff", + "email": "legoff.n@gmail.com" + }, + { + "name": "Phraseanet Team", + "email": "info@alchemy.fr", + "homepage": "http://www.phraseanet.com/" } ], - "description": "Symfony Process Component", - "homepage": "http://symfony.com" + "description": "A set of tools to build binary drivers", + "keywords": [ + "binary", + "driver" + ] }, { - "name": "symfony/filesystem", - "version": "v2.4.1", - "version_normalized": "2.4.1.0", - "target-dir": "Symfony/Component/Filesystem", + "name": "php-ffmpeg/php-ffmpeg", + "version": "0.3.x-dev", + "version_normalized": "0.3.9999999.9999999-dev", "source": { "type": "git", - "url": "https://github.com/symfony/Filesystem.git", - "reference": "b3c3b5a8108b3e5d604dc23241b4ea84a067fc78" + "url": "https://github.com/PHP-FFMpeg/PHP-FFMpeg.git", + "reference": "185fb5c33da594db7ffbf3f89d48e9841bc666a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/b3c3b5a8108b3e5d604dc23241b4ea84a067fc78", - "reference": "b3c3b5a8108b3e5d604dc23241b4ea84a067fc78", + "url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/185fb5c33da594db7ffbf3f89d48e9841bc666a0", + "reference": "185fb5c33da594db7ffbf3f89d48e9841bc666a0", "shasum": "" }, "require": { + "alchemy/binary-driver": "~1.5", + "doctrine/cache": "~1.0", + "evenement/evenement": "~1.0", + "neutron/temporary-filesystem": "~2.1, >=2.1.1", "php": ">=5.3.3" }, - "time": "2013-12-31 13:43:26", + "require-dev": { + "phpunit/phpunit": "~3.7", + "sami/sami": "~1.0", + "silex/silex": "~1.0" + }, + "suggest": { + "php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg" + }, + "time": "2013-10-21 12:13:46", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "0.4-dev" } }, - "installation-source": "dist", + "installation-source": "source", "autoload": { "psr-0": { - "Symfony\\Component\\Filesystem\\": "" + "FFMpeg": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -443,57 +479,87 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Romain Neutron", + "email": "imprec@gmail.com", + "homepage": "http://www.lickmychip.com/" }, { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Phraseanet Team", + "email": "info@alchemy.fr", + "homepage": "http://www.phraseanet.com/" } ], - "description": "Symfony Filesystem Component", - "homepage": "http://symfony.com" + "description": "FFMpeg PHP, an Object Oriented library to communicate with AVconv / ffmpeg", + "keywords": [ + "audio", + "audio processing", + "avconv", + "avprobe", + "ffmpeg", + "ffprobe", + "video", + "video processing" + ] }, { - "name": "neutron/temporary-filesystem", - "version": "2.1.1", - "version_normalized": "2.1.1.0", + "name": "sabre/vobject", + "version": "3.2.0", + "version_normalized": "3.2.0.0", "source": { "type": "git", - "url": "https://github.com/romainneutron/Temporary-Filesystem.git", - "reference": "6b21fa99fd452efea16b9a7adb7304ccfff854d0" + "url": "https://github.com/fruux/sabre-vobject.git", + "reference": "dd1dd19b6601cdc99408b70ec260052825f70b8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/romainneutron/Temporary-Filesystem/zipball/6b21fa99fd452efea16b9a7adb7304ccfff854d0", - "reference": "6b21fa99fd452efea16b9a7adb7304ccfff854d0", + "url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/dd1dd19b6601cdc99408b70ec260052825f70b8f", + "reference": "dd1dd19b6601cdc99408b70ec260052825f70b8f", "shasum": "" }, "require": { - "symfony/filesystem": "~2.0" + "ext-mbstring": "*", + "php": ">=5.3.1" }, "require-dev": { - "phpunit/phpunit": "~3.7" + "phpunit/phpunit": "*" }, - "time": "2013-10-10 10:58:09", + "time": "2014-04-02 23:53:27", + "bin": [ + "bin/vobject", + "bin/generate_vcards" + ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, "installation-source": "dist", "autoload": { "psr-0": { - "Neutron": "src" + "Sabre\\VObject": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Romain Neutron", - "email": "imprec@gmail.com", - "homepage": "http://www.lickmychip.com/" + "name": "Evert Pot", + "email": "evert@rooftopsolutions.nl", + "homepage": "http://evertpot.com/", + "role": "Developer" } ], - "description": "Symfony filesystem extension to handle temporary files" + "description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects", + "homepage": "https://github.com/fruux/sabre-vobject", + "keywords": [ + "VObject", + "iCalendar", + "jCal", + "jCard", + "vCard" + ] } ] diff --git a/vendor/monolog/monolog/CHANGELOG.mdown b/vendor/monolog/monolog/CHANGELOG.mdown index 5c71cbddbd..a657dbc293 100644 --- a/vendor/monolog/monolog/CHANGELOG.mdown +++ b/vendor/monolog/monolog/CHANGELOG.mdown @@ -1,3 +1,20 @@ +### 1.8.0 (2014-03-23) + + * Break: the LineFormatter now strips newlines by default because this was a bug, set $allowInlineLineBreaks to true if you need them + * Added BrowserConsoleHandler to send logs to any browser's console via console.log() injection in the output + * Added FilterHandler to filter records and only allow those of a given list of levels through to the wrapped handler + * Added FlowdockHandler to send logs to a Flowdock account + * Added RollbarHandler to send logs to a Rollbar account + * Added HtmlFormatter to send prettier log emails with colors for each log level + * Added GitProcessor to add the current branch/commit to extra record data + * Added a Monolog\Registry class to allow easier global access to pre-configured loggers + * Added support for the new official graylog2/gelf-php lib for GelfHandler, upgrade if you can by replacing the mlehner/gelf-php requirement + * Added support for HHVM + * Added support for Loggly batch uploads + * Added support for tweaking the content type and encoding in NativeMailerHandler + * Added $skipClassesPartials to tweak the ignored classes in the IntrospectionProcessor + * Fixed batch request support in GelfHandler + ### 1.7.0 (2013-11-14) * Added ElasticSearchHandler to send logs to an Elastic Search server diff --git a/vendor/monolog/monolog/README.mdown b/vendor/monolog/monolog/README.mdown index 64b4cfe36c..1179d57ee9 100644 --- a/vendor/monolog/monolog/README.mdown +++ b/vendor/monolog/monolog/README.mdown @@ -119,6 +119,7 @@ Handlers - _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance. - _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API. - _HipChatHandler_: Logs records to a [HipChat](http://hipchat.com) chat room using its API. +- _FlowdockHandler_: Logs records to a [Flowdock](https://www.flowdock.com/) account. ### Log specific servers and networked logging @@ -133,6 +134,7 @@ Handlers - _ZendMonitorHandler_: Logs records to the Zend Monitor present in Zend Server. - _NewRelicHandler_: Logs records to a [NewRelic](http://newrelic.com/) application. - _LogglyHandler_: Logs records to a [Loggly](http://www.loggly.com/) account. +- _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account. - _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server. ### Logging in development @@ -141,6 +143,8 @@ Handlers inline `console` messages within [FireBug](http://getfirebug.com/). - _ChromePHPHandler_: Handler for [ChromePHP](http://www.chromephp.com/), providing inline `console` messages within Chrome. +- _BrowserConsoleHandler_: Handler to send logs to browser's Javascript `console` with + no browser extension required. Most browsers supporting `console` API are supported. ### Log to databases @@ -171,6 +175,8 @@ Handlers for every log record. - _GroupHandler_: This handler groups other handlers. Every record received is sent to all the handlers it is configured with. +- _FilterHandler_: This handler only lets records of the given levels through + to the wrapped handler. - _TestHandler_: Used for testing, it records everything that is sent to it and has accessors to read out the information. @@ -178,14 +184,17 @@ Formatters ---------- - _LineFormatter_: Formats a log record into a one-line string. +- _HtmlFormatter_: Used to format log records into a human readable html table, mainly suitable for emails. - _NormalizerFormatter_: Normalizes objects/resources down to strings so a record can easily be serialized/encoded. - _ScalarFormatter_: Used to format log records into an associative array of scalar values. - _JsonFormatter_: Encodes a log record into json. - _WildfireFormatter_: Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler. - _ChromePHPFormatter_: Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler. -- _GelfFormatter_: Used to format log records into Gelf message instances, only useful for the GelfHandler. +- _GelfMessageFormatter_: Used to format log records into Gelf message instances, only useful for the GelfHandler. - _LogstashFormatter_: Used to format log records into [logstash](http://logstash.net/) event json, useful for any handler listed under inputs [here](http://logstash.net/docs/1.1.5/). - _ElasticaFormatter_: Used to format log records into an Elastica\Document object, only useful for the ElasticSearchHandler. +- _LogglyFormatter_: Used to format log records into Loggly messages, only useful for the LogglyHandler. +- _FlowdockFormatter_: Used to format log records into Flowdock messages, only useful for the FlowdockHandler. Processors ---------- @@ -196,6 +205,7 @@ Processors - _MemoryPeakUsageProcessor_: Adds the peak memory usage to a log record. - _ProcessIdProcessor_: Adds the process id to a log record. - _UidProcessor_: Adds a unique identifier to a log record. +- _GitProcessor_: Adds the current git branch and commit to a log record. Utilities --------- @@ -233,6 +243,7 @@ Frameworks Integration - [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin. - [Slim](http://www.slimframework.com/) is usable with Monolog via the [Slim-Monolog](https://github.com/Flynsarmy/Slim-Monolog) log writer. - [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog. +- [Aura.Web_Project](https://github.com/auraphp/Aura.Web_Project) comes out of the box with Monolog. Author ------ diff --git a/vendor/monolog/monolog/composer.json b/vendor/monolog/monolog/composer.json index 0939dd494a..2b059f31dc 100644 --- a/vendor/monolog/monolog/composer.json +++ b/vendor/monolog/monolog/composer.json @@ -18,27 +18,28 @@ }, "require-dev": { "phpunit/phpunit": "~3.7.0", - "mlehner/gelf-php": "1.0.*", - "raven/raven": "0.5.*", + "graylog2/gelf-php": "~1.0", + "raven/raven": "~0.5", "ruflin/elastica": "0.90.*", - "doctrine/couchdb": "dev-master", - "aws/aws-sdk-php": "~2.4.8" + "doctrine/couchdb": "~1.0@dev", + "aws/aws-sdk-php": "~2.4, >2.4.8" }, "suggest": { - "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "raven/raven": "Allow sending log messages to a Sentry server", "doctrine/couchdb": "Allow sending log messages to a CouchDB server", "ruflin/elastica": "Allow sending log messages to an Elastic Search server", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB" + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "rollbar/rollbar": "Allow sending log messages to Rollbar" }, "autoload": { - "psr-0": {"Monolog": "src/"} + "psr-4": {"Monolog\\": "src/Monolog"} }, "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.8.x-dev" } } } diff --git a/vendor/monolog/monolog/doc/extending.md b/vendor/monolog/monolog/doc/extending.md index fcd7af2b39..bb39ddcfe2 100644 --- a/vendor/monolog/monolog/doc/extending.md +++ b/vendor/monolog/monolog/doc/extending.md @@ -65,7 +65,7 @@ You can now use this handler in your logger: ```php pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')); +$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite'))); // You can now use your logger $logger->addInfo('My logger is now ready'); diff --git a/vendor/monolog/monolog/doc/usage.md b/vendor/monolog/monolog/doc/usage.md index 0312e90c21..846bd51a3e 100644 --- a/vendor/monolog/monolog/doc/usage.md +++ b/vendor/monolog/monolog/doc/usage.md @@ -8,7 +8,7 @@ Monolog is available on Packagist ([monolog/monolog](http://packagist.org/packag and as such installable via [Composer](http://getcomposer.org/). ```bash -php composer.phar require monolog/monolog '~1.4' +php composer.phar require monolog/monolog '~1.7' ``` If you do not use Composer, you can grab the code from GitHub, and use any diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php index 822af0ea43..206ec2499b 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -20,6 +20,34 @@ namespace Monolog\Formatter; */ class JsonFormatter implements FormatterInterface { + + protected $batch_mode; + + const BATCH_MODE_JSON = 1; + const BATCH_MODE_NEWLINES = 2; + + /** + * @param int $batch_mode + */ + public function __construct($batch_mode = self::BATCH_MODE_JSON) + { + $this->batch_mode = $batch_mode; + } + + /** + * The batch mode option configures the formatting style for + * multiple records. By default, multiple records will be + * formatted as a JSON-encoded array. However, for + * compatibility with some API endpoints, alternive styles + * are available. + * + * @return int + */ + public function getBatchMode() + { + return $this->batch_mode; + } + /** * {@inheritdoc} */ @@ -32,7 +60,46 @@ class JsonFormatter implements FormatterInterface * {@inheritdoc} */ public function formatBatch(array $records) + { + switch ($this->batch_mode) { + + case static::BATCH_MODE_NEWLINES: + return $this->formatBatchNewlines($records); + + case static::BATCH_MODE_JSON: + default: + return $this->formatBatchJson($records); + + } + } + + /** + * Return a JSON-encoded array of records. + * + * @param array $records + * @return string + */ + protected function formatBatchJson(array $records) { return json_encode($records); } + + /** + * Use new lines to separate records instead of a + * JSON-encoded array. + * + * @param array $records + * @return string + */ + protected function formatBatchNewlines(array $records) + { + $instance = $this; + + array_walk($records, function (&$value, $key) use ($instance) { + $value = $instance->format($value); + }); + + return implode("\n", $records); + } + } diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php index daa919bfa3..9ef0a64596 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -11,6 +11,8 @@ namespace Monolog\Formatter; +use Exception; + /** * Formats incoming records into a one-line string * @@ -24,14 +26,17 @@ class LineFormatter extends NormalizerFormatter const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; protected $format; + protected $allowInlineLineBreaks; /** - * @param string $format The format of the message - * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + * @param string $format The format of the message + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries */ - public function __construct($format = null, $dateFormat = null) + public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = false) { $this->format = $format ?: static::SIMPLE_FORMAT; + $this->allowInlineLineBreaks = $allowInlineLineBreaks; parent::__construct($dateFormat); } @@ -45,13 +50,13 @@ class LineFormatter extends NormalizerFormatter $output = $this->format; foreach ($vars['extra'] as $var => $val) { if (false !== strpos($output, '%extra.'.$var.'%')) { - $output = str_replace('%extra.'.$var.'%', $this->convertToString($val), $output); + $output = str_replace('%extra.'.$var.'%', $this->replaceNewlines($this->convertToString($val)), $output); unset($vars['extra'][$var]); } } foreach ($vars as $var => $val) { if (false !== strpos($output, '%'.$var.'%')) { - $output = str_replace('%'.$var.'%', $this->convertToString($val), $output); + $output = str_replace('%'.$var.'%', $this->replaceNewlines($this->convertToString($val)), $output); } } @@ -68,37 +73,41 @@ class LineFormatter extends NormalizerFormatter return $message; } - protected function normalize($data) + protected function normalizeException(Exception $e) { - if (is_bool($data) || is_null($data)) { - return var_export($data, true); + $previousText = ''; + if ($previous = $e->getPrevious()) { + do { + $previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); + } while ($previous = $previous->getPrevious()); } - if ($data instanceof \Exception) { - $previousText = ''; - if ($previous = $data->getPrevious()) { - do { - $previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); - } while ($previous = $previous->getPrevious()); - } - - return '[object] ('.get_class($data).': '.$data->getMessage().' at '.$data->getFile().':'.$data->getLine().$previousText.')'; - } - - return parent::normalize($data); + return '[object] ('.get_class($e).': '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')'; } protected function convertToString($data) { - if (null === $data || is_scalar($data)) { + if (null === $data || is_bool($data)) { + return var_export($data, true); + } + + if (is_scalar($data)) { return (string) $data; } - $data = $this->normalize($data); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { return $this->toJson($data, true); } return str_replace('\\/', '/', @json_encode($data)); } + + protected function replaceNewlines($str) + { + if ($this->allowInlineLineBreaks) { + return $str; + } + + return preg_replace('{[\r\n]+}', ' ', $str); + } } diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php index 765fed4566..dfa3cb9124 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php @@ -101,7 +101,6 @@ class NormalizerFormatter implements FormatterInterface ); $trace = $e->getTrace(); - array_shift($trace); foreach ($trace as $frame) { if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; diff --git a/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php index 81fc7a372e..3bb21b7131 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php @@ -141,8 +141,8 @@ abstract class AbstractHandler implements HandlerInterface /** * Sets the bubbling behavior. * - * @param Boolean $bubble true means that this handler allows bubbling. - * false means that bubbling is not permitted. + * @param Boolean $bubble true means that this handler allows bubbling. + * false means that bubbling is not permitted. * @return self */ public function setBubble($bubble) diff --git a/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php index cdcde2d55e..d968720c88 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -32,8 +32,8 @@ class CubeHandler extends AbstractProcessingHandler * Create a Cube handler * * @throws UnexpectedValueException when given url is not a valid url. - * A valid url must consists of three parts : protocol://host:port - * Only valid protocol used by Cube are http and udp + * A valid url must consists of three parts : protocol://host:port + * Only valid protocol used by Cube are http and udp */ public function __construct($url, $level = Logger::DEBUG, $bubble = true) { diff --git a/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php index 34d48e7506..790f6364de 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php @@ -12,31 +12,37 @@ namespace Monolog\Handler; use Gelf\IMessagePublisher; +use Gelf\PublisherInterface; +use InvalidArgumentException; use Monolog\Logger; -use Monolog\Handler\AbstractProcessingHandler; use Monolog\Formatter\GelfMessageFormatter; /** * Handler to send messages to a Graylog2 (http://www.graylog2.org) server * * @author Matt Lehner + * @author Benjamin Zikarsky */ class GelfHandler extends AbstractProcessingHandler { /** - * @var Gelf\IMessagePublisher the publisher object that sends the message to the server + * @var Publisher the publisher object that sends the message to the server */ protected $publisher; /** - * @param Gelf\IMessagePublisher $publisher a publisher object - * @param integer $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param PublisherInterface|IMessagePublisher $publisher a publisher object + * @param integer $level The minimum logging level at which this handler will be triggered + * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not */ - public function __construct(IMessagePublisher $publisher, $level = Logger::DEBUG, $bubble = true) + public function __construct($publisher, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); + if (!$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) { + throw new InvalidArgumentException("Invalid publisher, expected a Gelf\IMessagePublisher or Gelf\PublisherInterface instance"); + } + $this->publisher = $publisher; } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php index 4e7d6392de..accff037c1 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php @@ -47,7 +47,7 @@ interface HandlerInterface * * @param array $record The record to handle * @return Boolean true means that this handler handled the record, and that bubbling is not permitted. - * false means the record was either not processed or that this handler allows bubbling. + * false means the record was either not processed or that this handler allows bubbling. */ public function handle(array $record); diff --git a/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php index 6df3f06d24..38ce931cec 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php @@ -27,6 +27,16 @@ use Monolog\Logger; */ class HipChatHandler extends SocketHandler { + /** + * The maximum allowed length for the name used in the "from" field. + */ + const MAXIMUM_NAME_LENGTH = 15; + + /** + * The maximum allowed length for the message. + */ + const MAXIMUM_MESSAGE_LENGTH = 9500; + /** * @var string */ @@ -47,6 +57,11 @@ class HipChatHandler extends SocketHandler */ private $notify; + /** + * @var string + */ + private $format; + /** * @param string $token HipChat API Token * @param string $room The room that should be alerted of the message (Id or Name) @@ -55,9 +70,14 @@ class HipChatHandler extends SocketHandler * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param Boolean $useSSL Whether to connect via SSL. + * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages) */ - public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true) + public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text') { + if (!$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) { + throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.'); + } + $connectionString = $useSSL ? 'ssl://api.hipchat.com:443' : 'api.hipchat.com:80'; parent::__construct($connectionString, $level, $bubble); @@ -65,6 +85,7 @@ class HipChatHandler extends SocketHandler $this->name = $name; $this->notify = $notify; $this->room = $room; + $this->format = $format; } /** @@ -93,7 +114,7 @@ class HipChatHandler extends SocketHandler 'room_id' => $this->room, 'notify' => $this->notify, 'message' => $record['formatted'], - 'message_format' => 'text', + 'message_format' => $this->format, 'color' => $this->getAlertColor($record['level']), ); @@ -159,13 +180,19 @@ class HipChatHandler extends SocketHandler return true; } - $batchRecord = $this->combineRecords($records); + $batchRecords = $this->combineRecords($records); - if (!$this->isHandling($batchRecord)) { - return false; + $handled = false; + foreach ($batchRecords as $batchRecord) { + if ($this->isHandling($batchRecord)) { + $this->write($batchRecord); + $handled = true; + } } - $this->write($batchRecord); + if (!$handled) { + return false; + } return false === $this->bubble; } @@ -180,6 +207,9 @@ class HipChatHandler extends SocketHandler */ private function combineRecords($records) { + $batchRecord = null; + $batchRecords = array(); + $batchedMessages = array(); $messages = array(); $formattedMessages = array(); $level = 0; @@ -187,12 +217,7 @@ class HipChatHandler extends SocketHandler $datetime = null; foreach ($records as $record) { - $record = $this->processRecord($record); - $record['formatted'] = $this->getFormatter()->format($record); - - $messages[] = $record['message']; - $formattedMessages[] = $record['formatted']; if ($record['level'] > $level) { $level = $record['level']; @@ -202,18 +227,74 @@ class HipChatHandler extends SocketHandler if (null === $datetime) { $datetime = $record['datetime']; } + + $messages[] = $record['message']; + $messgeStr = implode(PHP_EOL, $messages); + $formattedMessages[] = $this->getFormatter()->format($record); + $formattedMessageStr = implode('', $formattedMessages); + + $batchRecord = array( + 'message' => $messgeStr, + 'formatted' => $formattedMessageStr, + 'context' => array(), + 'extra' => array(), + ); + + if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) { + // Pop the last message and implode the remainging messages + $lastMessage = array_pop($messages); + $lastFormattedMessage = array_pop($formattedMessages); + $batchRecord['message'] = implode(PHP_EOL, $messages); + $batchRecord['formatted'] = implode('', $formattedMessages); + + $batchRecords[] = $batchRecord; + $messages = array($lastMessage); + $formattedMessages = array($lastFormattedMessage); + + $batchRecord = null; + } } - $batchRecord = array( - 'message' => implode(PHP_EOL, $messages), - 'formatted' => implode('', $formattedMessages), - 'level' => $level, - 'level_name' => $levelName, - 'datetime' => $datetime, - 'context' => array(), - 'extra' => array(), - ); + if (null !== $batchRecord) { + $batchRecords[] = $batchRecord; + } + + // Set the max level and datetime for all records + foreach ($batchRecords as &$batchRecord) { + $batchRecord = array_merge( + $batchRecord, + array( + 'level' => $level, + 'level_name' => $levelName, + 'datetime' => $datetime + ) + ); + } + + return $batchRecords; + } + + /** + * Validates the length of a string. + * + * If the `mb_strlen()` function is available, it will use that, as HipChat + * allows UTF-8 characters. Otherwise, it will fall back to `strlen()`. + * + * Note that this might cause false failures in the specific case of using + * a valid name with less than 16 characters, but 16 or more bytes, on a + * system where `mb_strlen()` is unavailable. + * + * @param string $str + * @param int $length + * + * @return bool + */ + private function validateStringLength($str, $length) + { + if (function_exists('mb_strlen')) { + return (mb_strlen($str) <= $length); + } - return $batchRecord; + return (strlen($str) <= $length); } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php index 3033c0ba55..f97df482aa 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php @@ -17,16 +17,46 @@ use Monolog\Logger; * NativeMailerHandler uses the mail() function to send the emails * * @author Christophe Coevoet + * @author Mark Garrett */ class NativeMailerHandler extends MailHandler { + /** + * The email address to which the message is delivered + * @var string + */ protected $to; + + /** + * The subject of the email + * @var string + */ protected $subject; - protected $headers = array( - 'Content-type: text/plain; charset=utf-8' - ); + + /** + * Optional headers for the message + * @var array + */ + protected $headers = array(); + + /** + * The wordwrap length for the message + * @var integer + */ protected $maxColumnWidth; + /** + * The Content-type for the message + * @var string + */ + protected $contentType = 'text/plain'; + + /** + * The encoding for the message + * @var string + */ + protected $encoding = 'utf-8'; + /** * @param string|array $to The receiver of the mail * @param string $subject The subject of the mail @@ -45,7 +75,10 @@ class NativeMailerHandler extends MailHandler } /** - * @param string|array $headers Custom added headers + * Add headers to the message + * + * @param string|array $headers Custom added headers + * @return null */ public function addHeader($headers) { @@ -63,9 +96,52 @@ class NativeMailerHandler extends MailHandler protected function send($content, array $records) { $content = wordwrap($content, $this->maxColumnWidth); - $headers = implode("\r\n", $this->headers) . "\r\n"; + $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n"); + $headers .= 'Content-type: ' . $this->getContentType() . '; charset=' . $this->getEncoding() . "\r\n"; + if ($this->getContentType() == 'text/html' && false === strpos($headers, 'MIME-Version:')) { + $headers .= 'MIME-Version: 1.0' . "\r\n"; + } foreach ($this->to as $to) { mail($to, $this->subject, $content, $headers); } } + + /** + * @return string $contentType + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * @return string $encoding + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML + * messages. + * @return self + */ + public function setContentType($contentType) + { + $this->contentType = $contentType; + + return $this; + } + + /** + * @param string $encoding + * @return self + */ + public function setEncoding($encoding) + { + $this->encoding = $encoding; + + return $this; + } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php index 9408a031b8..b1dff9b64f 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -32,19 +32,19 @@ class PushoverHandler extends SocketHandler private $emergencyLevel; /** - * @param string $token Pushover api token - * @param string|array $users Pushover user id or array of ids the message will be sent to - * @param string $title Title sent to the Pushover API - * @param integer $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not - * the pushover.net app owner. OpenSSL is required for this option. - * @param integer $highPriorityLevel The minimum logging level at which this handler will start - * sending "high priority" requests to the Pushover API - * @param integer $emergencyLevel The minimum logging level at which this handler will start - * sending "emergency" requests to the Pushover API - * @param integer $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user. - * @param integer $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds). + * @param string $token Pushover api token + * @param string|array $users Pushover user id or array of ids the message will be sent to + * @param string $title Title sent to the Pushover API + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not + * the pushover.net app owner. OpenSSL is required for this option. + * @param integer $highPriorityLevel The minimum logging level at which this handler will start + * sending "high priority" requests to the Pushover API + * @param integer $emergencyLevel The minimum logging level at which this handler will start + * sending "emergency" requests to the Pushover API + * @param integer $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user. + * @param integer $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds). */ public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200) { diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php index 02c8261e8d..98e91691ac 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php @@ -14,7 +14,6 @@ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; -use Monolog\Handler\AbstractProcessingHandler; use Raven_Client; /** @@ -69,7 +68,7 @@ class RavenHandler extends AbstractProcessingHandler $level = $this->level; // filter records based on their level - $records = array_filter($records, function($record) use ($level) { + $records = array_filter($records, function ($record) use ($level) { return $record['level'] >= $level; }); @@ -78,7 +77,7 @@ class RavenHandler extends AbstractProcessingHandler } // the record with the highest severity is the "main" one - $record = array_reduce($records, function($highest, $record) { + $record = array_reduce($records, function ($highest, $record) { if ($record['level'] >= $highest['level']) { return $record; } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php index 18a0fcc5c1..a02ff516ee 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -105,7 +105,7 @@ class RotatingFileHandler extends StreamHandler } // Sorting the files by name to remove the older ones - usort($logFiles, function($a, $b) { + usort($logFiles, function ($a, $b) { return strcmp($b, $a); }); diff --git a/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php index 521b5751f1..281752949b 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -73,7 +73,8 @@ class StreamHandler extends AbstractProcessingHandler fwrite($this->stream, (string) $record['formatted']); } - private function customErrorHandler($code, $msg) { + private function customErrorHandler($code, $msg) + { $this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg); } } diff --git a/vendor/monolog/monolog/src/Monolog/Logger.php b/vendor/monolog/monolog/src/Monolog/Logger.php index 087dee2f09..4a74db3512 100644 --- a/vendor/monolog/monolog/src/Monolog/Logger.php +++ b/vendor/monolog/monolog/src/Monolog/Logger.php @@ -107,12 +107,15 @@ class Logger implements LoggerInterface */ protected static $timezone; + /** + * @var string + */ protected $name; /** * The handler stack * - * @var array of Monolog\Handler\HandlerInterface + * @var HandlerInterface[] */ protected $handlers; @@ -121,14 +124,14 @@ class Logger implements LoggerInterface * * To process records of a single handler instead, add the processor on that specific handler * - * @var array of callables + * @var callable[] */ protected $processors; /** - * @param string $name The logging channel - * @param array $handlers Optional stack of handlers, the first one in the array is called first, etc. - * @param array $processors Optional array of processors + * @param string $name The logging channel + * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. + * @param callable[] $processors Optional array of processors */ public function __construct($name, array $handlers = array(), array $processors = array()) { @@ -341,7 +344,7 @@ class Logger implements LoggerInterface */ public function addEmergency($message, array $context = array()) { - return $this->addRecord(static::EMERGENCY, $message, $context); + return $this->addRecord(static::EMERGENCY, $message, $context); } /** diff --git a/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php index a7de5d8ddc..a2c48ce6af 100644 --- a/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php +++ b/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php @@ -28,9 +28,12 @@ class IntrospectionProcessor { private $level; - public function __construct($level = Logger::DEBUG) + private $skipClassesPartials; + + public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array('Monolog\\')) { $this->level = $level; + $this->skipClassesPartials = $skipClassesPartials; } /** @@ -52,8 +55,15 @@ class IntrospectionProcessor array_shift($trace); $i = 0; - while (isset($trace[$i]['class']) && false !== strpos($trace[$i]['class'], 'Monolog\\')) { - $i++; + + while (isset($trace[$i]['class'])) { + foreach ($this->skipClassesPartials as $part) { + if (strpos($trace[$i]['class'], $part) !== false) { + $i++; + continue 2; + } + } + break; } // we should have the call source now diff --git a/vendor/symfony/process/Symfony/Component/Process/LICENSE b/vendor/symfony/process/Symfony/Component/Process/LICENSE index 88a57f8d8d..0b3292cf90 100644 --- a/vendor/symfony/process/Symfony/Component/Process/LICENSE +++ b/vendor/symfony/process/Symfony/Component/Process/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2013 Fabien Potencier +Copyright (c) 2004-2014 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/process/Symfony/Component/Process/Process.php b/vendor/symfony/process/Symfony/Component/Process/Process.php index e16df5aca5..a4bdfca90c 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Process.php +++ b/vendor/symfony/process/Symfony/Component/Process/Process.php @@ -17,7 +17,7 @@ use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Exception\RuntimeException; /** - * Process is a thin wrapper around proc_* functions to ease + * Process is a thin wrapper around proc_* functions to easily * start independent PHP processes. * * @author Fabien Potencier @@ -59,8 +59,8 @@ class Process private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; - private $incrementalOutputOffset; - private $incrementalErrorOutputOffset; + private $incrementalOutputOffset = 0; + private $incrementalErrorOutputOffset = 0; private $tty; private $useFileHandles = false; @@ -189,7 +189,8 @@ class Process * * @return integer The exit status code * - * @throws RuntimeException When process can't be launch or is stopped + * @throws RuntimeException When process can't be launched + * @throws RuntimeException When process stopped after receiving signal * * @api */ @@ -220,7 +221,7 @@ class Process * * @return Process The process itself * - * @throws RuntimeException When process can't be launch or is stopped + * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running */ public function start($callback = null) @@ -237,7 +238,11 @@ class Process $commandline = $this->commandline; if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) { - $commandline = 'cmd /V:ON /E:ON /C "'.$commandline.'"'; + $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')"'; + foreach ($this->processPipes->getFiles() as $offset => $filename) { + $commandline .= ' '.$offset.'>'.$filename; + } + if (!isset($this->options['bypass_shell'])) { $this->options['bypass_shell'] = true; } @@ -251,6 +256,11 @@ class Process $this->status = self::STATUS_STARTED; $this->processPipes->unblock(); + + if ($this->tty) { + return; + } + $this->processPipes->write(false, $this->stdin); $this->updateStatus(false); $this->checkTimeout(); @@ -266,7 +276,7 @@ class Process * * @return Process The new process * - * @throws RuntimeException When process can't be launch or is stopped + * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * * @see start() @@ -296,9 +306,12 @@ class Process * * @throws RuntimeException When process timed out * @throws RuntimeException When process stopped after receiving signal + * @throws LogicException When process is not yet started */ public function wait($callback = null) { + $this->requireProcessIsStarted(__FUNCTION__); + $this->updateStatus(false); if (null !== $callback) { $this->callback = $this->buildCallback($callback); @@ -316,10 +329,6 @@ class Process } if ($this->processInformation['signaled']) { - if ($this->isSigchildEnabled()) { - throw new RuntimeException('The process has been signaled.'); - } - throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig'])); } @@ -348,6 +357,7 @@ class Process * Sends a POSIX signal to the process. * * @param integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) + * * @return Process * * @throws LogicException In case the process is not running @@ -356,17 +366,7 @@ class Process */ public function signal($signal) { - if (!$this->isRunning()) { - throw new LogicException('Can not send signal on a non running process.'); - } - - if ($this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); - } - - if (true !== @proc_terminate($this->process, $signal)) { - throw new RuntimeException(sprintf('Error while sending signal `%d`.', $signal)); - } + $this->doSignal($signal, true); return $this; } @@ -376,10 +376,14 @@ class Process * * @return string The process output * + * @throws LogicException In case the process is not started + * * @api */ public function getOutput() { + $this->requireProcessIsStarted(__FUNCTION__); + $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); return $this->stdout; @@ -391,10 +395,14 @@ class Process * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * + * @throws LogicException In case the process is not started + * * @return string The process output since the last call */ public function getIncrementalOutput() { + $this->requireProcessIsStarted(__FUNCTION__); + $data = $this->getOutput(); $latest = substr($data, $this->incrementalOutputOffset); @@ -421,10 +429,14 @@ class Process * * @return string The process error output * + * @throws LogicException In case the process is not started + * * @api */ public function getErrorOutput() { + $this->requireProcessIsStarted(__FUNCTION__); + $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true); return $this->stderr; @@ -437,10 +449,14 @@ class Process * whole error output, this one returns the new error output since the last * call. * + * @throws LogicException In case the process is not started + * * @return string The process error output since the last call */ public function getIncrementalErrorOutput() { + $this->requireProcessIsStarted(__FUNCTION__); + $data = $this->getErrorOutput(); $latest = substr($data, $this->incrementalErrorOutputOffset); @@ -465,7 +481,7 @@ class Process /** * Returns the exit code returned by the process. * - * @return integer The exit status code + * @return null|integer The exit status code, null if the Process is not terminated * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * @@ -474,7 +490,7 @@ class Process public function getExitCode() { if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method'); + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); } $this->updateStatus(false); @@ -488,14 +504,18 @@ class Process * This method relies on the Unix exit code status standardization * and might not be relevant for other operating systems. * - * @return string A string representation for the exit status code + * @return null|string A string representation for the exit status code, null if the Process is not terminated. + * + * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @see http://tldp.org/LDP/abs/html/exitcodes.html * @see http://en.wikipedia.org/wiki/Unix_signal */ public function getExitCodeText() { - $exitcode = $this->getExitCode(); + if (null === $exitcode = $this->getExitCode()) { + return; + } return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error'; } @@ -520,13 +540,16 @@ class Process * @return Boolean * * @throws RuntimeException In case --enable-sigchild is activated + * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenSignaled() { + $this->requireProcessIsTerminated(__FUNCTION__); + if ($this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); @@ -542,13 +565,16 @@ class Process * @return integer * * @throws RuntimeException In case --enable-sigchild is activated + * @throws LogicException In case the process is not terminated * * @api */ public function getTermSignal() { + $this->requireProcessIsTerminated(__FUNCTION__); + if ($this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); @@ -563,10 +589,14 @@ class Process * * @return Boolean * + * @throws LogicException In case the process is not terminated + * * @api */ public function hasBeenStopped() { + $this->requireProcessIsTerminated(__FUNCTION__); + $this->updateStatus(false); return $this->processInformation['stopped']; @@ -579,10 +609,14 @@ class Process * * @return integer * + * @throws LogicException In case the process is not terminated + * * @api */ public function getStopSignal() { + $this->requireProcessIsTerminated(__FUNCTION__); + $this->updateStatus(false); return $this->processInformation['stopsig']; @@ -654,6 +688,12 @@ class Process { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { + if (defined('PHP_WINDOWS_VERSION_BUILD') && !$this->isSigchildEnabled()) { + exec(sprintf("taskkill /F /T /PID %d 2>&1", $this->getPid()), $output, $exitCode); + if ($exitCode > 0) { + throw new RuntimeException('Unable to kill the process'); + } + } proc_terminate($this->process); do { usleep(1000); @@ -661,7 +701,11 @@ class Process if ($this->isRunning() && !$this->isSigchildEnabled()) { if (null !== $signal || defined('SIGKILL')) { - $this->signal($signal ?: SIGKILL); + // avoid exception here : + // process is supposed to be running, but it might have stop + // just after this line. + // in any case, let's silently discard the error, we can not do anything + $this->doSignal($signal ?: SIGKILL, false); } } } @@ -671,8 +715,6 @@ class Process $this->close(); } - $this->status = self::STATUS_TERMINATED; - return $this->exitcode; } @@ -723,7 +765,7 @@ class Process } /** - * Gets the process timeout. + * Gets the process timeout (max. runtime). * * @return float|null The timeout in seconds or null if it's disabled */ @@ -733,9 +775,9 @@ class Process } /** - * Gets the process idle timeout. + * Gets the process idle timeout (max. time since last output). * - * @return float|null + * @return float|null The timeout in seconds or null if it's disabled */ public function getIdleTimeout() { @@ -743,7 +785,7 @@ class Process } /** - * Sets the process timeout. + * Sets the process timeout (max. runtime). * * To disable the timeout, set this value to null. * @@ -761,9 +803,11 @@ class Process } /** - * Sets the process idle timeout. + * Sets the process idle timeout (max. time since last output). * - * @param integer|float|null $timeout + * To disable the timeout, set this value to null. + * + * @param integer|float|null $timeout The timeout in seconds * * @return self The current Process instance. * @@ -791,7 +835,7 @@ class Process } /** - * Checks if the TTY mode is enabled. + * Checks if the TTY mode is enabled. * * @return Boolean true if the TTY mode is enabled, false otherwise */ @@ -856,7 +900,9 @@ class Process public function setEnv(array $env) { // Process can not handle env values that are arrays - $env = array_filter($env, function ($value) { if (!is_array($value)) { return true; } }); + $env = array_filter($env, function ($value) { + return !is_array($value); + }); $this->env = array(); foreach ($env as $key => $value) { @@ -978,13 +1024,17 @@ class Process */ public function checkTimeout() { + if ($this->status !== self::STATUS_STARTED) { + return; + } + if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); } - if (0 < $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { + if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); @@ -998,7 +1048,7 @@ class Process */ private function getDescriptors() { - $this->processPipes = new ProcessPipes($this->useFileHandles); + $this->processPipes = new ProcessPipes($this->useFileHandles, $this->tty); $descriptors = $this->processPipes->getDescriptors(); if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { @@ -1044,7 +1094,7 @@ class Process /** * Updates the status of the process, reads pipes. * - * @param Boolean $blocking Whether to use a clocking read call. + * @param Boolean $blocking Whether to use a blocking read call. */ protected function updateStatus($blocking) { @@ -1059,7 +1109,6 @@ class Process if (!$this->processInformation['running']) { $this->close(); - $this->status = self::STATUS_TERMINATED; } } @@ -1074,6 +1123,10 @@ class Process return self::$sigchild; } + if (!function_exists('phpinfo')) { + return self::$sigchild = false; + } + ob_start(); phpinfo(INFO_GENERAL); @@ -1104,6 +1157,7 @@ class Process * Reads pipes, executes callback. * * @param Boolean $blocking Whether to use blocking calls or not. + * @param Boolean $close Whether to close file handles or not. */ private function readPipes($blocking, $close) { @@ -1139,17 +1193,17 @@ class Process */ private function close() { - $exitcode = -1; - $this->processPipes->close(); if (is_resource($this->process)) { $exitcode = proc_close($this->process); + } else { + $exitcode = -1; } - $this->exitcode = $this->exitcode !== null ? $this->exitcode : -1; - $this->exitcode = -1 != $exitcode ? $exitcode : $this->exitcode; + $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1); + $this->status = self::STATUS_TERMINATED; - if (-1 == $this->exitcode && null !== $this->fallbackExitcode) { + if (-1 === $this->exitcode && null !== $this->fallbackExitcode) { $this->exitcode = $this->fallbackExitcode; } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention @@ -1176,4 +1230,73 @@ class Process $this->incrementalOutputOffset = 0; $this->incrementalErrorOutputOffset = 0; } + + /** + * Sends a POSIX signal to the process. + * + * @param integer $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) + * @param Boolean $throwException Whether to throw exception in case signal failed + * + * @return Boolean True if the signal was sent successfully, false otherwise + * + * @throws LogicException In case the process is not running + * @throws RuntimeException In case --enable-sigchild is activated + * @throws RuntimeException In case of failure + */ + private function doSignal($signal, $throwException) + { + if (!$this->isRunning()) { + if ($throwException) { + throw new LogicException('Can not send signal on a non running process.'); + } + + return false; + } + + if ($this->isSigchildEnabled()) { + if ($throwException) { + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); + } + + return false; + } + + if (true !== @proc_terminate($this->process, $signal)) { + if ($throwException) { + throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); + } + + return false; + } + + return true; + } + + /** + * Ensures the process is running or terminated, throws a LogicException if the process has a not started. + * + * @param $functionName The function name that was called. + * + * @throws LogicException If the process has not run. + */ + private function requireProcessIsStarted($functionName) + { + if (!$this->isStarted()) { + throw new LogicException(sprintf('Process must be started before calling %s.', $functionName)); + } + } + + /** + * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`. + * + * @param $functionName The function name that was called. + * + * @throws LogicException If the process is not yet terminated. + */ + private function requireProcessIsTerminated($functionName) + { + if (!$this->isTerminated()) { + throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName)); + } + } } diff --git a/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php b/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php index cde393e8bd..5317cd0883 100644 --- a/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php +++ b/vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php @@ -46,19 +46,34 @@ class ProcessUtils } $escapedArgument = ''; - foreach (preg_split('/([%"])/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { + $quote = false; + foreach (preg_split('/(")/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { if ('"' === $part) { $escapedArgument .= '\\"'; - } elseif ('%' === $part) { - $escapedArgument .= '^%'; + } elseif (self::isSurroundedBy($part, '%')) { + // Avoid environment variable expansion + $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%'; } else { - $escapedArgument .= escapeshellarg($part); + // escape trailing backslash + if ('\\' === substr($part, -1)) { + $part .= '\\'; + } + $quote = true; + $escapedArgument .= $part; } } + if ($quote) { + $escapedArgument = '"'.$escapedArgument.'"'; + } return $escapedArgument; } return escapeshellarg($argument); } + + private static function isSurroundedBy($arg, $char) + { + return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; + } } diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php b/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php index 4e486327b8..2f41d7627d 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Process\Tests; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Process; use Symfony\Component\Process\Exception\RuntimeException; +use Symfony\Component\Process\ProcessPipes; /** * @author Robert Schönthal @@ -81,6 +82,34 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase $this->assertLessThan(1.8, $duration); } + public function testAllOutputIsActuallyReadOnTermination() + { + // this code will result in a maximum of 2 reads of 8192 bytes by calling + // start() and isRunning(). by the time getOutput() is called the process + // has terminated so the internal pipes array is already empty. normally + // the call to start() will not read any data as the process will not have + // generated output, but this is non-deterministic so we must count it as + // a possibility. therefore we need 2 * ProcessPipes::CHUNK_SIZE plus + // another byte which will never be read. + $expectedOutputSize = ProcessPipes::CHUNK_SIZE * 2 + 2; + + $code = sprintf('echo str_repeat(\'*\', %d);', $expectedOutputSize); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code))); + + $p->start(); + // Let's wait enough time for process to finish... + // Here we don't call Process::run or Process::wait to avoid any read of pipes + usleep(500000); + + if ($p->isRunning()) { + $this->markTestSkipped('Process execution did not complete in the required time frame'); + } + + $o = $p->getOutput(); + + $this->assertEquals($expectedOutputSize, strlen($o)); + } + public function testCallbacksAreExecutedWithStart() { $data = ''; @@ -167,7 +196,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testGetErrorOutput() { - $p = new Process(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'))); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'))); $p->run(); $this->assertEquals(3, preg_match_all('/ERROR/', $p->getErrorOutput(), $matches)); @@ -175,7 +204,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testGetIncrementalErrorOutput() { - $p = new Process(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { usleep(50000); file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'))); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { usleep(100000); file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'))); $p->start(); while ($p->isRunning()) { @@ -186,7 +215,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testFlushErrorOutput() { - $p = new Process(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'))); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'))); $p->run(); $p->clearErrorOutput(); @@ -195,7 +224,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testGetOutput() { - $p = new Process(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++; usleep(500); }'))); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++; usleep(500); }'))); $p->run(); $this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches)); @@ -203,7 +232,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testGetIncrementalOutput() { - $p = new Process(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) { echo \' foo \'; usleep(50000); $n++; }'))); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) { echo \' foo \'; usleep(50000); $n++; }'))); $p->start(); while ($p->isRunning()) { @@ -214,7 +243,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testFlushOutput() { - $p = new Process(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++;}'))); + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++;}'))); $p->run(); $p->clearOutput(); @@ -240,11 +269,32 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase $this->markTestSkipped('Windows does have /dev/tty support'); } + $process = $this->getProcess('echo "foo" >> /dev/null && php -r "usleep(100000);"'); + $process->setTTY(true); + $process->start(); + $this->assertTrue($process->isRunning()); + $process->wait(); + + $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); + } + + public function testTTYCommandExitCode() + { + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->markTestSkipped('Windows does have /dev/tty support'); + } + $process = $this->getProcess('echo "foo" >> /dev/null'); $process->setTTY(true); $process->run(); - $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); + $this->assertTrue($process->isSuccessful()); + } + + public function testExitCodeTextIsNullWhenExitCodeIsNull() + { + $process = $this->getProcess(''); + $this->assertNull($process->getExitCodeText()); } public function testExitCodeText() @@ -260,11 +310,12 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testStartIsNonBlocking() { - $process = $this->getProcess('php -r "sleep(4);"'); + $process = $this->getProcess('php -r "usleep(500000);"'); $start = microtime(true); $process->start(); $end = microtime(true); - $this->assertLessThan(1 , $end-$start); + $this->assertLessThan(0.2, $end-$start); + $process->wait(); } public function testUpdateStatus() @@ -299,7 +350,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase { $process = $this->getProcess('php -m'); $process->run(); - $this->assertEquals(0, $process->getExitCode()); + $this->assertSame(0, $process->getExitCode()); } public function testStatus() @@ -351,10 +402,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testIsNotSuccessful() { - $process = $this->getProcess('php -r "sleep(4);"'); + $process = $this->getProcess('php -r "usleep(500000);throw new \Exception(\'BOUM\');"'); $process->start(); $this->assertTrue($process->isRunning()); - $process->stop(); + $process->wait(); $this->assertFalse($process->isSuccessful()); } @@ -445,7 +496,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase $process1->run(); $process2 = $process1->restart(); - usleep(300000); // wait for output + $process2->wait(); // wait for output // Ensure that both processed finished and the output is numeric $this->assertFalse($process1->isRunning()); @@ -472,7 +523,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testRunProcessWithTimeout() { $timeout = 0.5; - $process = $this->getProcess('php -r "sleep(3);"'); + $process = $this->getProcess('php -r "usleep(600000);"'); $process->setTimeout($timeout); $start = microtime(true); try { @@ -486,6 +537,19 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase $this->assertLessThan($timeout + Process::TIMEOUT_PRECISION, $duration); } + public function testCheckTimeoutOnNonStartedProcess() + { + $process = $this->getProcess('php -r "sleep(3);"'); + $process->checkTimeout(); + } + + public function testCheckTimeoutOnTerminatedProcess() + { + $process = $this->getProcess('php -v'); + $process->run(); + $process->checkTimeout(); + } + public function testCheckTimeoutOnStartedProcess() { $timeout = 0.5; @@ -552,7 +616,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testStartAfterATimeout() { - $process = $this->getProcess('php -r "while (true) {echo \'\'; usleep(1000); }"'); + $process = $this->getProcess('php -r "$n = 1000; while ($n--) {echo \'\'; usleep(1000); }"'); $process->setTimeout(0.1); try { $process->run(); @@ -567,10 +631,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase public function testGetPid() { - $process = $this->getProcess('php -r "sleep(1);"'); + $process = $this->getProcess('php -r "usleep(500000);"'); $process->start(); $this->assertGreaterThan(0, $process->getPid()); - $process->stop(); + $process->wait(); } public function testGetPidIsNullBeforeStart() @@ -630,6 +694,55 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase $process->signal(SIGHUP); } + /** + * @dataProvider provideMethodsThatNeedARunningProcess + */ + public function testMethodsThatNeedARunningProcess($method) + { + $process = $this->getProcess('php -m'); + $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', sprintf('Process must be started before calling %s.', $method)); + call_user_func(array($process, $method)); + } + + public function provideMethodsThatNeedARunningProcess() + { + return array( + array('getOutput'), + array('getIncrementalOutput'), + array('getErrorOutput'), + array('getIncrementalErrorOutput'), + array('wait'), + ); + } + + /** + * @dataProvider provideMethodsThatNeedATerminatedProcess + */ + public function testMethodsThatNeedATerminatedProcess($method) + { + $process = $this->getProcess('php -r "sleep(1);"'); + $process->start(); + try { + call_user_func(array($process, $method)); + $process->stop(0); + $this->fail('A LogicException must have been thrown'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Process\Exception\LogicException', $e); + $this->assertEquals(sprintf('Process must be terminated before calling %s.', $method), $e->getMessage()); + } + $process->stop(0); + } + + public function provideMethodsThatNeedATerminatedProcess() + { + return array( + array('hasBeenSignaled'), + array('getTermSignal'), + array('hasBeenStopped'), + array('getStopSignal'), + ); + } + private function verifyPosixIsEnabled() { if (defined('PHP_WINDOWS_VERSION_BUILD')) { diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php b/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php index a4db838256..d81abf4040 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php @@ -25,7 +25,7 @@ function handleSignal($signal) echo "received signal $name\n"; } -declare(ticks=1); +declare(ticks = 1); pcntl_signal(SIGTERM, 'handleSignal'); pcntl_signal(SIGINT, 'handleSignal'); diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php index 2982aff9f9..ee14fa9cbc 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php @@ -138,13 +138,13 @@ class ProcessBuilderTest extends \PHPUnit_Framework_TestCase public function testShouldEscapeArguments() { - $pb = new ProcessBuilder(array('%path%', 'foo " bar')); + $pb = new ProcessBuilder(array('%path%', 'foo " bar', '%baz%baz')); $proc = $pb->getProcess(); if (defined('PHP_WINDOWS_VERSION_BUILD')) { - $this->assertSame('^%"path"^% "foo "\\"" bar"', $proc->getCommandLine()); + $this->assertSame('^%"path"^% "foo \\" bar" "%baz%baz"', $proc->getCommandLine()); } else { - $this->assertSame("'%path%' 'foo \" bar'", $proc->getCommandLine()); + $this->assertSame("'%path%' 'foo \" bar' '%baz%baz'", $proc->getCommandLine()); } } diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php b/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php index 603fac53e7..8ba94c114d 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php @@ -27,18 +27,22 @@ class ProcessUtilsTest extends \PHPUnit_Framework_TestCase { if (defined('PHP_WINDOWS_VERSION_BUILD')) { return array( + array('"\"php\" \"-v\""', '"php" "-v"'), array('"foo bar"', 'foo bar'), array('^%"path"^%', '%path%'), - array('"<|>"\\"" "\\""\'f"', '<|>" "\'f'), + array('"<|>\\" \\"\'f"', '<|>" "\'f'), array('""', ''), + array('"with\trailingbs\\\\"', 'with\trailingbs\\'), ); } return array( + array("'\"php\" \"-v\"'", '"php" "-v"'), array("'foo bar'", 'foo bar'), array("'%path%'", '%path%'), array("'<|>\" \"'\\''f'", '<|>" "\'f'), array("''", ''), + array("'with\\trailingbs\\'", 'with\trailingbs\\'), ); } } diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php b/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php index d6ae226990..798e66a571 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php @@ -15,6 +15,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest { /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testGetExitCode() { @@ -23,6 +24,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testGetExitCodeIsNullOnStart() { @@ -31,6 +33,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testGetExitCodeIsNullOnWhenStartingAgain() { @@ -39,6 +42,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testExitCodeCommandFailed() { @@ -47,6 +51,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessIsSignaledIfStopped() { @@ -55,6 +60,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessWithTermSignal() { @@ -63,6 +69,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessIsNotSignaled() { @@ -71,6 +78,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage his PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessWithoutTermSignal() { @@ -79,6 +87,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testCheckTimeoutOnStartedProcess() { @@ -87,6 +96,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved. */ public function testGetPid() { @@ -95,6 +105,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved. */ public function testGetPidIsNullBeforeStart() { @@ -103,6 +114,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved. */ public function testGetPidIsNullAfterRun() { @@ -111,6 +123,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testExitCodeText() { @@ -122,6 +135,16 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. + */ + public function testExitCodeTextIsNullWhenExitCodeIsNull() + { + parent::testExitCodeTextIsNullWhenExitCodeIsNull(); + } + + /** + * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testIsSuccessful() { @@ -130,6 +153,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testIsSuccessfulOnlyAfterTerminated() { @@ -138,6 +162,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. */ public function testIsNotSuccessful() { @@ -146,6 +171,16 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. + */ + public function testTTYCommandExitCode() + { + parent::testTTYCommandExitCode(); + } + + /** + * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process can not be signaled. */ public function testSignal() { @@ -154,6 +189,7 @@ class SigchildDisabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessWithoutTermSignalIsNotSignaled() { diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php b/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php index 3da512a4fc..65dd4bb573 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php @@ -15,6 +15,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest { /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessIsSignaledIfStopped() { @@ -23,6 +24,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessWithTermSignal() { @@ -31,6 +33,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessIsNotSignaled() { @@ -39,6 +42,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessWithoutTermSignal() { @@ -47,6 +51,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved. */ public function testGetPid() { @@ -55,6 +60,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved. */ public function testGetPidIsNullBeforeStart() { @@ -63,6 +69,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved. */ public function testGetPidIsNullAfterRun() { @@ -79,6 +86,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. The process can not be signaled. */ public function testSignal() { @@ -87,6 +95,7 @@ class SigchildEnabledProcessTest extends AbstractProcessTest /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. */ public function testProcessWithoutTermSignalIsNotSignaled() { @@ -103,6 +112,14 @@ class SigchildEnabledProcessTest extends AbstractProcessTest $this->markTestSkipped('Signal is not supported in sigchild environment'); } + public function testStartAfterATimeout() + { + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->markTestSkipped('Restarting a timed-out process on Windows is not supported in sigchild environment'); + } + parent::testStartAfterATimeout(); + } + /** * {@inheritdoc} */ diff --git a/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php b/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php index 6655acf4ec..69ad3d5b09 100644 --- a/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php +++ b/vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php @@ -27,106 +27,123 @@ class SimpleProcessTest extends AbstractProcessTest public function testGetExitCode() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case parent::testGetExitCode(); } public function testExitCodeCommandFailed() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case parent::testExitCodeCommandFailed(); } public function testProcessIsSignaledIfStopped() { - $this->skipIfPHPSigchild(); + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); parent::testProcessIsSignaledIfStopped(); } public function testProcessWithTermSignal() { - $this->skipIfPHPSigchild(); + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); parent::testProcessWithTermSignal(); } public function testProcessIsNotSignaled() { - $this->skipIfPHPSigchild(); + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); parent::testProcessIsNotSignaled(); } public function testProcessWithoutTermSignal() { - $this->skipIfPHPSigchild(); + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); parent::testProcessWithoutTermSignal(); } public function testExitCodeText() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use exitcode that is not available in this case parent::testExitCodeText(); } public function testIsSuccessful() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use PID that is not available in this case parent::testIsSuccessful(); } public function testIsNotSuccessful() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use PID that is not available in this case parent::testIsNotSuccessful(); } public function testGetPid() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use PID that is not available in this case parent::testGetPid(); } public function testGetPidIsNullBeforeStart() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use PID that is not available in this case parent::testGetPidIsNullBeforeStart(); } public function testGetPidIsNullAfterRun() { - $this->skipIfPHPSigchild(); + $this->skipIfPHPSigchild(); // This test use PID that is not available in this case parent::testGetPidIsNullAfterRun(); } public function testSignal() { - $this->skipIfPHPSigchild(); + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); parent::testSignal(); } - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - */ + public function testProcessWithoutTermSignalIsNotSignaled() + { + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved'); + parent::testProcessWithoutTermSignalIsNotSignaled(); + } + + public function testProcessThrowsExceptionWhenExternallySignaled() + { + $this->skipIfPHPSigchild(); // This test use PID that is not available in this case + parent::testProcessThrowsExceptionWhenExternallySignaled(); + } + + public function testExitCodeIsAvailableAfterSignal() + { + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); + parent::testExitCodeIsAvailableAfterSignal(); + } + public function testSignalProcessNotRunning() { - $this->skipIfPHPSigchild(); + $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', 'Can not send signal on a non running process.'); parent::testSignalProcessNotRunning(); } - /** - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - */ public function testSignalWithWrongIntSignal() { - $this->skipIfPHPSigchild(); + if ($this->enabledSigchild) { + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); + } else { + $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Error while sending signal `-4`.'); + } parent::testSignalWithWrongIntSignal(); } - /** - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - */ public function testSignalWithWrongNonIntSignal() { - $this->skipIfPHPSigchild(); + if ($this->enabledSigchild) { + $this->expectExceptionIfPHPSigchild('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); + } else { + $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'Error while sending signal `Céphalopodes`.'); + } parent::testSignalWithWrongNonIntSignal(); } @@ -144,4 +161,11 @@ class SimpleProcessTest extends AbstractProcessTest $this->markTestSkipped('Your PHP has been compiled with --enable-sigchild, this test can not be executed'); } } + + private function expectExceptionIfPHPSigchild($classname, $message) + { + if ($this->enabledSigchild) { + $this->setExpectedException($classname, $message); + } + } }