/** * Sanitize a date or date/time string, making sure it is valid, and return it * * If no dateFormat is specified, date will be returned as a unix timestamp. * If given date is invalid or empty, NULL will be returned. * If $value is an integer or string of all numbers, it is always assumed to be a unix timestamp. * * @param string|int $value Date string or unix timestamp * @param string|null $format Format of date string ($value) in any wireDate(), date() or strftime() format. * @param array $options Options to modify behavior: * - returnFormat: wireDate() format to return date in. If not specified, then the $format argument is used. * - min: Minimum allowed date in $format or unix timestamp format. Null is returned when date is less than this. * - max: Maximum allowed date in $format or unix timestamp format. Null is returned when date is more than this. * - default: Default value to return if no value specified. * @return string|int|null * */ public function date($value, $format = null, array $options = array()) { $defaults = array('returnFormat' => $format, 'min' => '', 'max' => '', 'default' => null); $options = array_merge($defaults, $options); if (empty($value)) { return $options['default']; } if (!is_string($value) && !is_int($value)) { $value = $this->string($value); } if (ctype_digit("{$value}")) { // value is in unix timestamp format // make sure it resolves to a valid date $value = strtotime(date('Y-m-d H:i:s', (int) $value)); } else { $value = strtotime($value); } // value is now a unix timestamp if (empty($value)) { return null; } if (!empty($options['min'])) { // if value is less than minimum required, return null/error $min = ctype_digit("{$options['min']}") ? (int) $options['min'] : (int) wireDate('ts', $options['min']); if ($value < $min) { return null; } } if (!empty($options['max'])) { // if value is more than max allowed, return null/error $max = ctype_digit("{$options['max']}") ? (int) $options['max'] : (int) wireDate('ts', $options['max']); if ($value > $max) { return null; } } if (!empty($options['returnFormat'])) { $value = wireDate($options['returnFormat'], $value); } return empty($value) ? null : $value; }
/** * Debug info specific to Page objects * * @param Page $page * @return array * */ protected function Page(Page $page) { $info = array('instanceID' => $page->instanceID, 'id' => $page->id, 'name' => $page->name, 'namePrevious' => '', 'path' => $page->path(), 'status' => implode(', ', $page->status(true)), 'statusPrevious' => 0, 'template' => $page->template ? $page->template->name : '', 'templatePrevious' => '', 'parent' => $page->parent ? $page->parent->path : '', 'parentPrevious' => '', 'numChildren' => $page->numChildren(), 'sort' => $page->sort, 'sortfield' => $page->sortfield, 'created' => $page->created, 'modified' => $page->modified, 'createdUser' => $page->createdUser ? $page->createdUser->name : $page->created_users_id, 'modifiedUser' => $page->modifiedUser ? $page->modifiedUser->name : $page->modified_users_id); if ($page->namePrevious) { $info['namePrevious'] = $page->namePrevious; } else { unset($info['namePrevious']); } if ($page->statusPrevious !== null) { $info['statusPrevious'] = implode(', ', $page->status(true, $page->statusPrevious)); } else { unset($info['statusPrevious']); } if ($page->templatePrevious) { $info['templatePrevious'] = $page->templatePrevious->name; } else { unset($info['templatePrevious']); } if ($page->parentPrevious) { $info['parentPrevious'] = $page->parentPrevious->path(); } else { unset($info['parentPrevious']); } if ($page->isNew) { $info['isNew'] = 1; } $info['isLoaded'] = (int) $page->isLoaded(); $info['outputFormatting'] = (int) $page->outputFormatting(); if ($page->quietMode) { $info['quietMode'] = 1; } foreach (array('created', 'modified') as $key) { $info[$key] = wireDate($this->wire('config')->dateFormat, $info[$key]) . " " . "(" . wireDate('relative', $info[$key]) . ")"; } return $info; }
/** * Render the comment * * This is the default rendering for development/testing/demonstration purposes * * It may be used for production, but only if it meets your needs already. Typically you'll want to render the comments * using your own code in your templates. * * @see CommentArray::render() * @return string * */ public function renderItem(Comment $comment, $depth = 0) { $text = $comment->getFormatted('text'); $cite = $comment->getFormatted('cite'); $gravatar = ''; if ($this->options['useGravatar']) { $imgUrl = $comment->gravatar($this->options['useGravatar'], $this->options['useGravatarImageset']); if ($imgUrl) { $gravatar = "\n\t\t<img class='CommentGravatar' src='{$imgUrl}' alt='{$cite}' />"; } } $website = ''; if ($comment->website) { $website = $comment->getFormatted('website'); } if ($website) { $cite = "<a href='{$website}' rel='nofollow' target='_blank'>{$cite}</a>"; } $created = wireDate($this->options['dateFormat'], $comment->created); if (empty($this->options['commentHeader'])) { $header = "<span class='CommentCite'>{$cite}</span> <small class='CommentCreated'>{$created}</small> "; if ($this->options['useVotes']) { $header .= $this->renderVotes($comment); } } else { $header = str_replace(array('{cite}', '{created}'), array($cite, $created), $this->options['commentHeader']); if (strpos($header, '{votes}') !== false) { $header = str_replace('{votes}', $this->renderVotes($comment), $header); } } $liClass = ''; $replies = $this->options['depth'] > 0 ? $this->renderList($comment->id, $depth + 1) : ''; if ($replies) { $liClass .= ' CommentHasReplies'; } if ($comment->status == Comment::statusPending) { $liClass .= ' CommentStatusPending'; } else { if ($comment->status == Comment::statusSpam) { $liClass .= ' CommentStatusSpam'; } } $out = "\n\t<li id='Comment{$comment->id}' class='CommentListItem{$liClass}' data-comment='{$comment->id}'>" . $gravatar . "\n\t\t<p class='CommentHeader'>{$header}</p>" . "\n\t\t<div class='CommentText'>" . "\n\t\t\t<p>{$text}</p>" . "\n\t\t</div>"; if ($this->options['usePermalink']) { $permalink = $comment->getPage()->httpUrl; $urlSegmentStr = $this->wire('input')->urlSegmentStr; if ($urlSegmentStr) { $permalink .= rtrim($permalink, '/') . $urlSegmentStr . '/'; } $permalink .= '#Comment' . $comment->id; $permalink = "<a class='CommentActionPermalink' href='{$permalink}'>" . $this->_('Permalink') . "</a>"; } else { $permalink = ''; } if ($this->options['depth'] > 0 && $depth < $this->options['depth']) { $out .= "\n\t\t<div class='CommentFooter'>" . "\n\t\t\t<p class='CommentAction'>" . "\n\t\t\t\t<a class='CommentActionReply' data-comment-id='{$comment->id}' href='#Comment{$comment->id}'>" . $this->_('Reply') . "</a> " . ($permalink ? "\n\t\t\t\t{$permalink}" : "") . "\n\t\t\t</p>" . "\n\t\t</div>"; if ($replies) { $out .= $replies; } } else { $out .= "\n\t\t<div class='CommentFooter'></div>"; } $out .= "\n\t</li>"; return $out; }
/** * Convert a log line to an entry array * * @param $line * @return array * */ public function lineToEntry($line) { $parts = explode("\t", $line, 4); if (count($parts) == 2) { $entry = array('date' => $parts[0], 'user' => '', 'url' => '', 'text' => $parts[1]); } else { if (count($parts) == 3) { $entry = array('date' => $parts[0], 'user' => strpos($parts[1], '/') === false ? $parts[1] : '', 'url' => strpos($parts[1], '/') !== false ? $parts[1] : '', 'text' => $parts[2]); } else { $entry = array('date' => isset($parts[0]) ? $parts[0] : '', 'user' => isset($parts[1]) ? $parts[1] : '', 'url' => isset($parts[2]) ? $parts[2] : '', 'text' => isset($parts[3]) ? $parts[3] : ''); } } $entry['date'] = wireDate(wire('config')->dateFormat, strtotime($entry['date'])); $entry['user'] = wire('sanitizer')->pageName($entry['user']); if ($entry['url'] == 'page?') { $entry['url'] = false; } if ($entry['user'] == 'user?') { $entry['user'] = false; } return $entry; }
/** * Get the value of a requested Page property * * @param string $key * @return mixed * @see __get * */ public function get($key) { if (is_array($key)) { $key = implode('|', $key); } $value = null; switch ($key) { case 'parent_id': case 'parentID': $value = $this->parent ? $this->parent->id : 0; break; case 'child': $value = $this->child(); break; case 'children': case 'subpages': // PW1 $value = $this->children(); break; case 'has_parent': case 'hasParent': $value = $this->parents(); break; case 'parent': case 'parents': case 'rootParent': case 'siblings': case 'next': case 'prev': case 'url': case 'path': case 'outputFormatting': case 'isTrash': $value = $this->{$key}(); break; case 'httpUrl': case 'httpURL': $value = $this->httpUrl(); break; case 'fieldgroup': case 'fields': $value = $this->template->fieldgroup; break; case 'template_id': case 'templates_id': case 'templateID': case 'templatesID': $value = $this->template ? $this->template->id : 0; break; case 'template': case 'templatePrevious': case 'parentPrevious': case 'namePrevious': case 'statusPrevious': case 'isLoaded': case 'isNew': case 'pageNum': case 'instanceID': $value = $this->{$key}; break; case 'out': case 'output': $value = $this->output(); break; case 'filesManager': $value = $this->filesManager(); break; case 'name': $value = $this->settings['name']; break; case 'modified_users_id': case 'modifiedUsersID': case 'modifiedUserID': $value = (int) $this->settings['modified_users_id']; break; case 'created_users_id': case 'createdUsersID': case 'createdUserID': $value = (int) $this->settings['created_users_id']; break; case 'modifiedUser': case 'createdUser': if (!$this->{$key}) { $_key = str_replace('User', '', $key) . '_users_id'; $u = $this->wire('user'); if ($this->settings[$_key] == $u->id) { $this->set($key, $u); // prevent possible recursion loop } else { $u = $this->wire('users')->get((int) $this->settings[$_key]); $this->set($key, $u); } } $value = $this->{$key}; if ($value) { $value->of($this->of()); } break; case 'urlSegment': $value = $this->wire('input')->urlSegment1; // deprecated, but kept for backwards compatibility break; case 'accessTemplate': $value = $this->getAccessTemplate(); break; case 'num_children': case 'numChildren': $value = $this->settings['numChildren']; break; case 'numChildrenVisible': case 'numVisibleChildren': case 'hasChildren': $value = $this->numChildren(true); break; case 'editUrl': case 'editURL': $value = $this->editUrl(); break; case 'statusStr': $value = implode(' ', $this->status(true)); break; case 'modifiedStr': case 'createdStr': case 'publishedStr': $value = $this->settings[str_replace('Str', '', $key)]; $value = $value ? wireDate($this->wire('config')->dateFormat, $value) : ''; break; default: if ($key && isset($this->settings[(string) $key])) { return $this->settings[$key]; } // populate a formatted string with {tag} vars if (strpos($key, '{') !== false && strpos($key, '}')) { return $this->getMarkup($key); } if (($value = $this->getFieldFirstValue($key)) !== null) { return $value; } if (($value = $this->getFieldValue($key)) !== null) { return $value; } // if there is a selector, we'll assume they are using the get() method to get a child if (Selectors::stringHasOperator($key)) { return $this->child($key); } // check if it's a field.subfield property if (strpos($key, '.') && ($value = $this->getFieldSubfieldValue($key)) !== null) { return $value; } // optionally let a hook look at it if (self::isHooked('Page::getUnknown()')) { $value = $this->getUnknown($key); } } return $value; }
/** * Format a date with the given PHP date() or PHP strftime() format * * @param int $value Unix timestamp of date * @param string $format date() or strftime() format string to use for formatting * @return string Formatted date string * */ public function formatDate($value, $format) { if (!$value) { return ''; } if (!strlen($format) || $format == 'U' || $format == '%s') { return (int) $value; } // unix timestamp $relativeStr = ''; if (strpos($format, '!') !== false) { if (function_exists('wireDate')) { if (preg_match('/([!][relativ]+-?)/', $format, $matches)) { $relativeStr = wireDate(ltrim($matches[1], '!'), $value); $format = str_replace($matches[1], '///', $format); } } else { // usage outside of ProcessWire, relative dates not supported } } if (strpos($format, '%') !== false) { // use strftime() if format string contains a % if (strpos($format, '%-') !== false) { // not all systems support the '%-' option in strftime to trim leading zeros // so we are doing our own implementation here $TRIM0 = true; $format = str_replace('%-', 'TRIM0%', $format); } else { $TRIM0 = false; } $value = strftime($format, $value); if ($TRIM0) { $value = str_replace(array('TRIM00', 'TRIM0'), '', $value); } } else { if (function_exists('wireDate')) { // use ProcessWire's wireDate() $value = wireDate($format, $value); } else { // usage outside of ProcessWire $value = date($format, $value); } } if (strlen($relativeStr)) { $value = str_replace('///', $relativeStr, $value); } return $value; }