mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 16:48:49 +01:00
- methods to combine and split status, quantity and role
- $ignore_acl parameter for calendar_boupdate::delete() - removed setting owner always as participant: owner is allowed to remove himself as participant from an event (owner only get's set, if there are no other participants in BO)
This commit is contained in:
parent
95e36754ce
commit
bb5511cc9f
@ -1081,54 +1081,54 @@ class calendar_bo
|
||||
switch(gettype($date))
|
||||
{
|
||||
case 'string': // YYYYMMDD or iso8601 YYYY-MM-DDThh:mm:ss[Z|[+-]hh:mm] string
|
||||
if (is_numeric($date) && $date > 21000000)
|
||||
{
|
||||
$date = (int) $date; // this is already as timestamp
|
||||
break;
|
||||
}
|
||||
// evaluate evtl. added timezone
|
||||
if (strlen($date) > 12)
|
||||
{
|
||||
if (substr($date,-1) == 'Z')
|
||||
if (is_numeric($date) && $date > 21000000)
|
||||
{
|
||||
$time_offset = date('Z');
|
||||
$date = (int) $date; // this is already as timestamp
|
||||
break;
|
||||
}
|
||||
elseif(preg_match('/([+-]{1})([0-9]{2}):?([0-9]{2})$/',$date,$matches))
|
||||
// evaluate evtl. added timezone
|
||||
if (strlen($date) > 12)
|
||||
{
|
||||
$time_offset = date('Z')-($matches[1] == '+' ? 1 : -1)*(3600*$matches[2]+60*$matches[3]);
|
||||
if (substr($date,-1) == 'Z')
|
||||
{
|
||||
$time_offset = date('Z');
|
||||
}
|
||||
elseif(preg_match('/([+-]{1})([0-9]{2}):?([0-9]{2})$/',$date,$matches))
|
||||
{
|
||||
$time_offset = date('Z')-($matches[1] == '+' ? 1 : -1)*(3600*$matches[2]+60*$matches[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// removing all non-nummerical chars, gives YYYYMMDDhhmmss, independent of the iso8601 format
|
||||
$date = str_replace(array('-',':','T','Z',' ','+'),'',$date);
|
||||
$date = array(
|
||||
'year' => (int) substr($date,0,4),
|
||||
'month' => (int) substr($date,4,2),
|
||||
'day' => (int) substr($date,6,2),
|
||||
'hour' => (int) substr($date,8,2),
|
||||
'minute' => (int) substr($date,10,2),
|
||||
'second' => (int) substr($date,12,2),
|
||||
);
|
||||
// fall-through
|
||||
// removing all non-nummerical chars, gives YYYYMMDDhhmmss, independent of the iso8601 format
|
||||
$date = str_replace(array('-',':','T','Z',' ','+'),'',$date);
|
||||
$date = array(
|
||||
'year' => (int) substr($date,0,4),
|
||||
'month' => (int) substr($date,4,2),
|
||||
'day' => (int) substr($date,6,2),
|
||||
'hour' => (int) substr($date,8,2),
|
||||
'minute' => (int) substr($date,10,2),
|
||||
'second' => (int) substr($date,12,2),
|
||||
);
|
||||
// fall-through
|
||||
case 'array': // day, month and year keys
|
||||
if (isset($date['raw']) && $date['raw']) // we already have a timestamp
|
||||
{
|
||||
$date = $date['raw'];
|
||||
if (isset($date['raw']) && $date['raw']) // we already have a timestamp
|
||||
{
|
||||
$date = $date['raw'];
|
||||
break;
|
||||
}
|
||||
if (!isset($date['year']) && isset($date['full']))
|
||||
{
|
||||
$date['year'] = (int) substr($date['full'],0,4);
|
||||
$date['month'] = (int) substr($date['full'],4,2);
|
||||
$date['day'] = (int) substr($date['full'],6,2);
|
||||
}
|
||||
$date = adodb_mktime((int)$date['hour'],(int)$date['minute'],(int)$date['second'],(int)$date['month'],
|
||||
(int) (isset($date['day']) ? $date['day'] : $date['mday']),(int)$date['year']);
|
||||
break;
|
||||
}
|
||||
if (!isset($date['year']) && isset($date['full']))
|
||||
{
|
||||
$date['year'] = (int) substr($date['full'],0,4);
|
||||
$date['month'] = (int) substr($date['full'],4,2);
|
||||
$date['day'] = (int) substr($date['full'],6,2);
|
||||
}
|
||||
$date = adodb_mktime((int)$date['hour'],(int)$date['minute'],(int)$date['second'],(int)$date['month'],
|
||||
(int) (isset($date['day']) ? $date['day'] : $date['mday']),(int)$date['year']);
|
||||
break;
|
||||
case 'integer': // already a timestamp
|
||||
break;
|
||||
break;
|
||||
default: // eg. boolean, means now in user-time (!)
|
||||
$date = $this->now_su;
|
||||
break;
|
||||
$date = $this->now_su;
|
||||
break;
|
||||
}
|
||||
if ($time_offset)
|
||||
{
|
||||
@ -1490,13 +1490,7 @@ class calendar_bo
|
||||
$names = array();
|
||||
foreach($event['participants'] as $id => $status)
|
||||
{
|
||||
$quantity = $role = '';
|
||||
if (strlen($status) > 1 && preg_match('/^.([0-9]*)(.*)$/',$status,$matches))
|
||||
{
|
||||
if ((int)$matches[1] > 1) $quantity = (int)$matches[1];
|
||||
$role = $matches[2];
|
||||
}
|
||||
$status = $status[0];
|
||||
calendar_so::split_status($status,$quantity,$role);
|
||||
|
||||
if ($status == 'G' && !$show_group_invitation) continue; // dont show group-invitation
|
||||
|
||||
@ -1526,8 +1520,22 @@ class calendar_bo
|
||||
{
|
||||
$status = '('.$this->verbose_status[$status].')';
|
||||
}
|
||||
$names[$id] = $this->participant_name($id).($quantity ? ' ('.$quantity.')' : '').
|
||||
' '.$status.($role ? ' '.lang(str_replace('X-','',$role)) : '');
|
||||
$names[$id] = $this->participant_name($id).($quantity > 1 ? ' ('.$quantity.')' : '').' '.$status;
|
||||
|
||||
// add role, if not a regular participant
|
||||
if ($role != 'REQ-PARTICIPANT')
|
||||
{
|
||||
// allow to use cats as roles (beside regular iCal ones)
|
||||
if (substr($role,0,6) == 'X-CAT-' && ($cat_id = (int)substr($role,6)) > 0)
|
||||
{
|
||||
$role = $GLOBALS['egw']->categories->id2name($cat_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$role = lang(str_replace('X-','',$role));
|
||||
}
|
||||
$names[$id] .= ' '.$role;
|
||||
}
|
||||
}
|
||||
return $names;
|
||||
}
|
||||
|
@ -103,12 +103,12 @@ class calendar_boupdate extends calendar_bo
|
||||
// set owner as participant if none is given
|
||||
if (!is_array($event['participants']) || !count($event['participants']))
|
||||
{
|
||||
$event['participants'][$event['owner']] = 'U';
|
||||
$event['participants'] = array($event['owner'] => 'U');
|
||||
}
|
||||
// set the status of the current user to 'A' = accepted
|
||||
if (isset($event['participants'][$this->user]) && $event['participants'][$this->user] != 'A')
|
||||
if (isset($event['participants'][$this->user]) && $event['participants'][$this->user][0] != 'A')
|
||||
{
|
||||
$event['participants'][$this->user] = 'A';
|
||||
$event['participants'][$this->user][0] = 'A';
|
||||
}
|
||||
}
|
||||
// check if user has the permission to update / create the event
|
||||
@ -792,14 +792,15 @@ class calendar_boupdate extends calendar_bo
|
||||
*
|
||||
* @param int $cal_id id of the event to delete
|
||||
* @param int $recur_date=0 if a single event from a series should be deleted, its date
|
||||
* @param boolean $ignore_acl=false true for no ACL check, default do ACL check
|
||||
* @return boolean true on success, false on error (usually permission denied)
|
||||
*/
|
||||
function delete($cal_id,$recur_date=0)
|
||||
function delete($cal_id,$recur_date=0,$ignore_acl=false)
|
||||
{
|
||||
$event = $this->read($cal_id,$recur_date);
|
||||
|
||||
if (!($event = $this->read($cal_id,$recur_date)) ||
|
||||
!$this->check_perms(EGW_ACL_DELETE,$event))
|
||||
!$ignore_acl && !$this->check_perms(EGW_ACL_DELETE,$event))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -271,14 +271,7 @@ class calendar_ical extends calendar_boupdate
|
||||
// RB: MAILTO href contains only the email-address, NO cn!
|
||||
$attributes['ATTENDEE'][] = $info['email'] ? 'MAILTO:'.$info['email'] : '';
|
||||
// ROLE={CHAIR|REQ-PARTICIPANT|OPT-PARTICIPANT|NON-PARTICIPANT|X-*}
|
||||
$role = 'REQ-PARTICIPANT';
|
||||
$quantity = '';
|
||||
if (strlen($status) > 1 && preg_match('/^.([0-9]*)(.*)$/',$status,$matches))
|
||||
{
|
||||
if ((int)$matches[1] > 1) $quantity = (int)$matches[1];
|
||||
if ($matches[2]) $role = $matches[2];
|
||||
$status = $status[0];
|
||||
}
|
||||
calendar_so::split_status($status,$quantity,$role);
|
||||
// RSVP={TRUE|FALSE} // resonse expected, not set in eGW => status=U
|
||||
$rsvp = $status == 'U' ? 'TRUE' : 'FALSE';
|
||||
// PARTSTAT={NEEDS-ACTION|ACCEPTED|DECLINED|TENTATIVE|DELEGATED|COMPLETED|IN-PROGRESS} everything from delegated is NOT used by eGW atm.
|
||||
@ -308,7 +301,7 @@ class calendar_ical extends calendar_boupdate
|
||||
'CUTYPE' => $cutype,
|
||||
'RSVP' => $rsvp,
|
||||
)+($info['type'] != 'e' ? array('X-EGROUPWARE-UID' => $uid) : array())+
|
||||
($quantity ? array('X-EGROUPWARE-QUANTITY' => $quantity) : array());
|
||||
($quantity > 1 ? array('X-EGROUPWARE-QUANTITY' => $quantity) : array());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1893,19 +1886,18 @@ class calendar_ical extends calendar_boupdate
|
||||
case 'ATTENDEE':
|
||||
if (isset($attributes['params']['PARTSTAT']))
|
||||
{
|
||||
$event['participants'][$uid] = $this->status_ical2egw[strtoupper($attributes['params']['PARTSTAT'])];
|
||||
$status = $this->status_ical2egw[strtoupper($attributes['params']['PARTSTAT'])];
|
||||
}
|
||||
elseif (isset($attributes['params']['STATUS']))
|
||||
{
|
||||
$event['participants'][$uid] = $this->status_ical2egw[strtoupper($attributes['params']['STATUS'])];
|
||||
$status = $this->status_ical2egw[strtoupper($attributes['params']['STATUS'])];
|
||||
}
|
||||
else
|
||||
{
|
||||
$event['participants'][$uid] = ($uid == $event['owner'] ? 'A' : 'U');
|
||||
$status = ($uid == $event['owner'] ? 'A' : 'U');
|
||||
}
|
||||
// add quantiy and ROLE
|
||||
if ((int)$attributes['params']['X-EGROUPWARE-QUANTITY'] > 1) $event['participants'][$uid] .= (int)$attributes['params']['X-EGROUPWARE-QUANTITY'];
|
||||
if ($attributes['params']['ROLE']) $event['participants'][$uid] .= $attributes['params']['ROLE'];
|
||||
// add quantity and role
|
||||
$event['participants'][$uid] = calendar_so::combine_status($status,$attributes['params']['X-EGROUPWARE-QUANTITY'],$attributes['params']['ROLE']);
|
||||
break;
|
||||
case 'ORGANIZER':
|
||||
if (is_numeric($uid))
|
||||
@ -1916,6 +1908,7 @@ class calendar_ical extends calendar_boupdate
|
||||
{
|
||||
$event['owner'] = $this->user;
|
||||
}
|
||||
// RalfBecker: this is not allways true, owner can choose to NOT participate in EGroupware
|
||||
$event['participants'][$uid] = 'A';
|
||||
break;
|
||||
}
|
||||
|
@ -112,9 +112,12 @@ class calendar_so
|
||||
*/
|
||||
function read($ids,$recur_date=0)
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length']))
|
||||
{
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
@ -193,22 +196,12 @@ class calendar_so
|
||||
'cal_recur_date' => $recur_date,
|
||||
),__LINE__,__FILE__,false,'ORDER BY cal_user_type DESC,'.self::STATUS_SORT,'calendar') as $row) // DESC puts users before resources and contacts
|
||||
{
|
||||
// if the type is not an ordinary user (eg. contact or resource)...
|
||||
if ($row['cal_user_type'] && $row['cal_user_type'] != 'u')
|
||||
{
|
||||
// prefix the id with the type
|
||||
$user_id = $row['cal_user_type'].$row['cal_user_id'];
|
||||
// and append quantity
|
||||
if ($row['cal_quantity'] > 1) $row['cal_status'] .= $row['cal_quantity'];
|
||||
// append role to status, if != 'REQ-PARTICIPANT'
|
||||
if ($row['cal_role'] != 'REQ-PARTICIPANT') $row['cal_status'] .= $row['cal_role'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$user_id = (int) $row['cal_user_id'];
|
||||
}
|
||||
$events[$row['cal_id']]['participants'][$user_id] = $row['cal_status'];
|
||||
$events[$row['cal_id']]['participant_types'][$row['cal_user_type']][$row['cal_user_id']] = $row['cal_status'];
|
||||
// combine all participant data in uid and status values
|
||||
$uid = self::combine_user($row['cal_user_type'],$row['cal_user_id']);
|
||||
$status = self::combine_status($row['cal_status'],$row['cal_quantity'],$row['cal_role']);
|
||||
|
||||
$events[$row['cal_id']]['participants'][$uid] = $status;
|
||||
$events[$row['cal_id']]['participant_types'][$row['cal_user_type']][$row['cal_user_id']] = $status;
|
||||
}
|
||||
|
||||
// custom fields
|
||||
@ -420,11 +413,9 @@ class calendar_so
|
||||
|
||||
if (!isset($events[$id])) continue; // not needed first entry of recuring event
|
||||
|
||||
// add quantity
|
||||
if ($row['cal_quantity'] > 1) $row['cal_status'] .= $row['cal_quantity'];
|
||||
// append role to status, if != 'REQ-PARTICIPANT'
|
||||
if ($row['cal_role'] != 'REQ-PARTICIPANT') $row['cal_status'] .= $row['cal_role'];
|
||||
$events[$id]['participants'][$this->combine_user($row['cal_user_type'],$row['cal_user_id'])] = $row['cal_status'];
|
||||
// combine all participant data in uid and status values
|
||||
$events[$id]['participants'][self::combine_user($row['cal_user_type'],$row['cal_user_id'])] =
|
||||
self::combine_status($row['cal_status'],$row['cal_quantity'],$row['cal_role']);
|
||||
}
|
||||
/* custom fields are not shown in the regular views, so we can ignore them here for the moment
|
||||
foreach($this->db->select($this->extra_table,'*',array('cal_id'=>$ids),__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
@ -522,7 +513,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
//echo "<p>socal::save(,$change_since) event="; _debug_array($event);
|
||||
//echo '<p>'.__METHOD__."(,$change_since) event="; _debug_array($event);
|
||||
//error_log(__METHOD__."(".str_replace(array("\n",' '),'',print_r($event,true)).",$set_recurrences,$change_since,$etag)");
|
||||
|
||||
$cal_id = (int) $event['id'];
|
||||
@ -555,13 +546,6 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
return 0; // wrong etag, someone else updated the entry
|
||||
}
|
||||
if (!is_null($etag)) ++$etag;
|
||||
// events need to have at least one participant, default to the owner
|
||||
if (!isset($event['cal_participants'])) {
|
||||
$event['cal_participants'] = array($event['cal_owner'] => 'A');
|
||||
}
|
||||
if (!isset($event['cal_participants'][$event['cal_owner']])) {
|
||||
$event['cal_participants'][$event['cal_owner']] = 'A';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -576,15 +560,6 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
return false;
|
||||
}
|
||||
$etag = 0;
|
||||
// new events need to have at least one participant, default to the owner
|
||||
if (!isset($event['cal_participants']))
|
||||
{
|
||||
$event['cal_participants'] = array($event['cal_owner'] => 'A');
|
||||
}
|
||||
if (!isset($event['cal_participants'][$event['cal_owner']]))
|
||||
{
|
||||
$event['cal_participants'][$event['cal_owner']] = 'A';
|
||||
}
|
||||
}
|
||||
if (!isset($event['cal_uid']) || strlen($event['cal_uid']) < $minimum_uid_length)
|
||||
{
|
||||
@ -795,7 +770,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
* @param string|int $user_id id
|
||||
* @return string|int combined id
|
||||
*/
|
||||
function combine_user($user_type,$user_id)
|
||||
static function combine_user($user_type,$user_id)
|
||||
{
|
||||
if (!$user_type || $user_type == 'u')
|
||||
{
|
||||
@ -811,7 +786,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
* @param string &$user_type 1-char type: 'u' = user, ...
|
||||
* @param string|int &$user_id id
|
||||
*/
|
||||
function split_user($uid,&$user_type,&$user_id)
|
||||
static function split_user($uid,&$user_type,&$user_id)
|
||||
{
|
||||
if (is_numeric($uid))
|
||||
{
|
||||
@ -825,6 +800,42 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine status, quantity and role into one value
|
||||
*
|
||||
* @param string $status
|
||||
* @param int $quantity
|
||||
* @param string $role
|
||||
* @return string
|
||||
*/
|
||||
static function combine_status($status,$quantity,$role)
|
||||
{
|
||||
if ((int)$quantity > 1) $status .= (int)$quantity;
|
||||
if ($role != 'REQ-PARTICIPANT') $status .= $role;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* splits the combined status, quantity and role
|
||||
*
|
||||
* @param string &$status I: combined value, O: status letter: U, T, A, R
|
||||
* @param int &$quantity only O: quantity
|
||||
* @param string &$role only O: role
|
||||
*/
|
||||
static function split_status(&$status,&$quantity,&$role)
|
||||
{
|
||||
$quantity = 1;
|
||||
$role = 'REQ-PARTICIPANT';
|
||||
|
||||
if (strlen($status) > 1 && preg_match('/^.([0-9]*)(.*)$/',$status,$matches))
|
||||
{
|
||||
if ((int)$matches[1] > 0) $quantity = (int)$matches[1];
|
||||
$role = $matches[2];
|
||||
$status = $status[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* updates the participants of an event, taken into account the evtl. recurrences of the event(!)
|
||||
*
|
||||
@ -835,12 +846,12 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
*/
|
||||
function participants($cal_id,$participants,$change_since=0)
|
||||
{
|
||||
//echo "<p>socal::participants($cal_id,".print_r($participants,true).",$change_since)</p>\n";
|
||||
//echo '<p>'.__METHOD__."($cal_id,".print_r($participants,true).",$change_since)</p>\n";
|
||||
|
||||
// remove group-invitations, they are NOT stored in the db
|
||||
foreach($participants as $uid => $status)
|
||||
{
|
||||
if ($status == 'G')
|
||||
if ($status[0] == 'G')
|
||||
{
|
||||
unset($participants[$uid]);
|
||||
}
|
||||
@ -902,7 +913,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
// existing participants must not be updated
|
||||
foreach($this->db->select($this->user_table,'DISTINCT cal_user_type,cal_user_id',$where,__LINE__,__FILE__,false,'','calendar') as $row)
|
||||
{
|
||||
$existing_participants[] = $this->combine_user($row['cal_user_type'],$row['cal_user_id']);
|
||||
$existing_participants[] = self::combine_user($row['cal_user_type'],$row['cal_user_id']);
|
||||
}
|
||||
}
|
||||
if (!count($recurrences)) $recurrences[] = 0; // insert the default one
|
||||
@ -912,16 +923,13 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
if (in_array($uid,$existing_participants)) continue; // don't update existing participants
|
||||
|
||||
$id = null;
|
||||
$this->split_user($uid,$type,$id);
|
||||
self::split_user($uid,$type,$id);
|
||||
self::split_status($status,$quantity,$role);
|
||||
$set = array(
|
||||
'cal_status' => $status !== true ? $status[0] : 'U',
|
||||
'cal_quantity' => substr($status,1) > 1 ? (int)substr($status,1) : 1,
|
||||
'cal_status' => $status,
|
||||
'cal_quantity' => $quantity,
|
||||
'cal_role' => $role,
|
||||
);
|
||||
// update role if set, it's apended to status and quantity
|
||||
if (strlen($status) > 1 && preg_match('/^.[0-9]*(.*)$/',$status,$matches))
|
||||
{
|
||||
$set['cal_role'] = $matches[1];
|
||||
}
|
||||
foreach($recurrences as $recur_date)
|
||||
{
|
||||
$this->db->insert($this->user_table,$set,array(
|
||||
@ -1147,8 +1155,9 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
$datetime = $GLOBALS['egw']->datetime;
|
||||
$now = ($now_su ? $now_su : time() + $datetime->this->tz_offset);
|
||||
$modifier = $GLOBALS['egw_info']['user']['account_id'];
|
||||
$this->db->update($this->cal_table, array('cal_modified' => $now, 'cal_modifier' => $modifier),
|
||||
$this->db->update($this->cal_table, array('cal_modified' => $now, 'cal_modifier' => $modifier),
|
||||
array('cal_id' => $cal_id), __LINE__, __FILE__, 'calendar');
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
@ -1180,11 +1189,12 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
{
|
||||
// update the modification information of the related event
|
||||
list(,$cal_id) = explode(':',$id);
|
||||
if ($cal_id) {
|
||||
if ($cal_id)
|
||||
{
|
||||
$datetime = $GLOBALS['egw']->datetime;
|
||||
$now = ($now_su ? $now_su : time() + $datetime->this->tz_offset);
|
||||
$modifier = $GLOBALS['egw_info']['user']['account_id'];
|
||||
$this->db->update($this->cal_table, array('cal_modified' => $now, 'cal_modifier' => $modifier),
|
||||
$this->db->update($this->cal_table, array('cal_modified' => $now, 'cal_modifier' => $modifier),
|
||||
array('cal_id' => $cal_id), __LINE__, __FILE__, 'calendar');
|
||||
}
|
||||
return $this->async->cancel_timer($id);
|
||||
@ -1384,5 +1394,4 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
sort($days);
|
||||
return $days;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user