\s*)?\[\s*(pagebreak\s*\]|(header\s*=\s*([^\]]*)\]))(\s*<\/p>)?/mi';
/* regex to parse
breaks */
public $re_tag = '/(
\s*)?
\s*(.*?)\s*<\/h3>(\s*<\/p>)?/mi';
/**
* Retrieve an instance of the Pagination class.
*
* @return an instance of the Pagination class.
*
*/
public static function instance() {
if (!self::$instance) {
self::$instance = new Pagination();
}
return self::$instance;
}
/**
* Paginate text by character count.
*
* @param $text
* The text to paginate.
* @param $cutoff
* The length of characters to cut text into.
*
*/
public function paginate($text, $cutoff) {
$textsize = strlen($text);
do {
$section = $this->parseText($text, $cutoff);
$this->page[] = $section;
$textsize = strlen($text);
}
while ($textsize > 0);
}
/**
* Return the pagination style currently being used.
*
* @param $type
* The node type.
* @return
* The pagination style the node type is using.
*
*/
public function getStyle($type) {
$this->style = $this->getSettings('style', $type);
return $this->style;
}
/**
* Return the pagination value currently being used.
*
* @param $type
* The node type.
* @return
* The pagination value the node type is using.
*
*/
public function getValue($type) {
$this->value = $this->getSettings('value', $type);
return $this->value;
}
/**
* Return the page headers for a specific node.
*
* @param $nid
* The node ID of the node to be queried.
* @return
* An array of page headers.
*
*/
public function getHeaders($nid = 0) {
if (!$nid) {
return array();
}
static $query;
if (!$query && $this->value > PAGINATION_AUTO) {
$result = db_select('node_pagination', 'n')
->fields('n', array('headers') )
->condition('nid', $nid, '=')
->execute()
->fetchObject();
$headers = isset($result->headers) ? unserialize($result->headers) : array();
foreach($headers as $key=>$header) {
// Page 1 is always the node title
$this->headers[$key + 1] = $header;
}
}
return $this->headers;
}
/**
* Return the page count.
*
* @return
* An integer corresponding to the total number of pages.
*
*/
public function getPageCount() {
return count($this->page);
}
/**
* Return the content of the page by page number.
*
* @param $page
* The page number to return content for.
* @return
* The content of the page.
*
*/
public function getPage($page) {
$section = isset($this->page[$page]) ? $this->page[$page] : '';
return $section;
}
/**
* Returns the value of $_GET['page']
*
* @return
* An integer value corresponding to the current page number, or "show" if
* showing the full page.
*
*/
public function getPageVar() {
$page = isset($_GET['page']) ? $_GET['page'] : 0;
// $page = $page > 0 ? --$page : $page; //drupal pattern
return $page;
}
/**
* Return a themed pager (Drupal default).
*
* @return
* HTML corresponding to a themed Drupal pager.
*
*/
public function getPager() {
global $pager_page_array, $pager_total;
$pager_page_array = explode(',', (int) $this->getPageVar() );
$pager_total[0] = $this->getPageCount();
$pager_page_array[0] = max(0, min( (int) $pager_page_array[0], (int) $pager_total[0]) );
$pager = theme('pager');
// Drupal default pager is 0 based, we'll use 1 based for ours
$regex = '#(\?|\&)page=(.+?)(\"|&|/)#se';
$pager = preg_replace($regex, "'$1page='.($2).''.stripslashes('$3').''", $pager); //drupal pattern
return $pager;
}
/**
* Return a themed table of contents.
*
* @param $nid
* The nid of the node.
* @param $ignore_title
* Boolean value to indicate whether "Table of Contents" string should not
* be rendered.
* @return
* HTML corresponding to a themed ToC.
*
*/
public function getToc($nid, $ignore_title = FALSE) {
if (!$nid) {
return;
}
drupal_add_css(drupal_get_path('module', 'pagination') . '/css/pagination.css');
$toc = array();
$headers = $this->getHeaders($nid);
$headers[0] = menu_get_active_title();
foreach($headers as $key => $header) {
$page = $key + 1;
$header = str_replace(array('
', '
'), '', $header);
$options = array(
'attributes' => array(
'title' => t('Go to page !page', array('!page' => $page) ),
),
'query' => array('page' => $page-1),
);
$toc[] = array(
'data' => ($this->getPageVar() == $key) ? check_plain($header) : l($header, $_GET['q'], $options),
'class' => array( (($this->getPageVar())-1 == $key) ? 'pagination-toc-item current' : 'pagination-toc-item'), //drupal pattern
);
}
$items = theme('item_list', array(
'items' => $toc,
'type' => variable_get('pagination_list_type', 'ul'),
'attributes' => array('class' => array('pagination-toc-list') ),
));
// Avoid problems with special chars displaying, likely not an exhaustive regex
$items = preg_replace('#&(\S{2,7}[^;];)#e', "'&$1'", $items);
$toc = theme('pagination_toc', array(
'toc' => $ignore_title ? NULL : t('Table of Contents:'),
'title' => drupal_get_title(),
'pages' => $items,
));
return $toc;
}
/**
* Return pagination settings by content type.
*
* @param $setting
* The pagination setting to return. [value | style].
* @param $type
* The node type.
* @return
* An array of pagination settings for a specific node type.
*
*/
protected function getSettings($setting, $type) {
static $pagination = array();
if (!isset($pagination[$type]) ) {
$result = db_select('pagination', 'p')
->fields('p')
->condition('type', $type, '=')
->execute()
->fetchObject();
$pagination[$type] = array(
'style' => isset($result->style) ? $result->style : 0,
'value' => isset($result->paginate) ? $result->paginate : 0,
);
}
$result = isset($pagination[$type][$setting]) ? $pagination[$type][$setting] : 0;
return $result;
}
/**
* Set the page headers.
*
* @param $header
* The page header to add to the stack.
*
*/
protected function setHeader($header) {
static $first;
if (!$first and $this->value < PAGINATION_AUTO) {
// Manual paging should have a default header set for page 1
$first = TRUE;
$this->headers[] = t('Page 1');
}
$this->headers[] = $header;
}
/**
* Handle pagination depending on pagination style
*
* @param $text
* The text to paginate.
* @param $cutoff
* The length of text to create sections from.
* @return
* A string representing a section of text.
*
*/
protected function parseText(&$text, $cutoff) {
$page_count = empty($this->headers) ? count($this->headers) + 1 : count($this->headers);
$section = '';
switch ($cutoff) {
case 1:
// Manual breaks w/custom headers, for [ header = random ] we expect:
// 0: [ header = HEADER TEXT ]
// 4: HEADER TEXT
// for [ pagebreak ] we expect:
// 0: [ pagebreak ]
preg_match($this->re_custom, $text, $matches);
if (isset($matches[0]) ) {
$header = isset($matches[4]) && $matches[4] ? $matches[4] : t('Page !num', array('!num' => $page_count + 1) );
$section = $this->parseSection($text, $matches, 1, 5);
$this->setHeader($header);
}
else {
// No matches, send back full text
$section = $text;
$text = '';
}
break;
case 2:
// Manual breaks w/h3 tags, we except:
// 0: HEADER TEXT
// 2: HEADER TEXT
$tag = 'h' . variable_get('pagination_header', 3);
if ('h3' !== $tag) {
$this->re_tag = str_replace('h3', $tag, $this->re_tag);
}
preg_match($this->re_tag, $text, $matches);
if (isset($matches[0]) ) {
$header = isset($matches[2]) ? $matches[2] : t('Page !num', array('!num' => $page_count + 1) );
$section = $this->parseSection($text, $matches, 1, 3);
$this->setHeader($header);
}
else {
// No matches, send back full text
$section = $text;
$text = '';
}
break;
default:
// Paging by words, we'll use the english approximate 5 chars per word (+ space)
$header = t('Page !num', array('!num' => $page_count + 1) );
$section = $this->parseChunk($text, $cutoff * 6);
$text = substr($text, strlen($section) );
$this->setHeader($header);
break;
}
return $section;
}
/**
* Handle splitting of sections in odd edge cases.
*
* @param $text
* The text to parse.
* @param $matches
* An array of matches.
* @param $start
* An integer corresponding to the start tag position within the text.
* @param $end
* An integer corresponding to the end tag position within the text.
*
*/
protected function parseSection(&$text, $matches, $start, $end) {
$open = isset($matches[$start]) && !isset($matches[$end]) ? $matches[$start] : '';
$close = isset($matches[$end]) && $matches[$end] && isset($matches[$start]) && !$matches[$start] ? $matches[$end] : '';
$split = strpos($text, $matches[0]);
$section = substr($text, 0, $split) . $close;
$text = $open . substr($text, $split + strlen($matches[0]) );
return $section;
}
/**
* Handle words per page chunking.
*
* @param $text
* The text to parse.
* @param $size
* The "maximum" length to create sections from the text.
* @return
* The chunk of text created.
*
*/
protected function parseChunk($text, $size) {
return text_summary($text, NULL, $size);
}
}