Skip to content

Instantly share code, notes, and snippets.

@texnixe
Last active August 14, 2023 06:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save texnixe/637b4096032a722370696d5d750b9918 to your computer and use it in GitHub Desktop.
Save texnixe/637b4096032a722370696d5d750b9918 to your computer and use it in GitHub Desktop.
Collection of custom Kirby page, pages, field etc. methods
<?php
// page methods
// check if page has Parents
page::$methods['hasParents'] = function($page) {
return $page->parents()->count();
};
// get max nesting level of page
page::$methods['maxDepth'] = function($page) {
foreach($page->index() as $p) {
$depth[] = $p->depth();
}
return max($depth);
};
// get index of page in collection
page::$methods['getIndex'] = function($page, $collection) {
$index = $collection->indexOf($page);
return $index;
};
// get next page of a given children collection (e.g. filtered collection)
page::$methods['getNext'] = function($page, Children $siblings, $sort = array(), $visibility = false) {
if($sort) $siblings = call(array($siblings, 'sortBy'), $sort);
$index = $siblings->indexOf($page);
if($index === false) return null;
if($visibility) {
$siblings = $siblings->offset($index+1);
$siblings = $siblings->{$visibility}();
return $siblings->first();
} else {
return $siblings->nth($index + 1);
}
};
// get prev page of a given children collection (e.g. filtered collection)
page::$methods['getPrev'] = function($page, Children $siblings, $sort = array(), $visibility = false) {
if($sort) $siblings = call(array($siblings, 'sortBy'), $sort);
$index = $siblings->indexOf($page);
if($index === false or $index === 0) return null;
if($visibility) {
$siblings = $siblings->limit($index);
$siblings = $siblings->{$visibility}();
return $siblings->last();
} else {
return $siblings->nth($index - 1);
}
};
page::$methods['getContent'] = function($page, $field) {
if($page->$field()->exists() && $page->$field()->isNotEmpty()) {
return $page->$field()->kt();
} else {
foreach($page->parents() as $page) {
if($page->$field()->isNotEmpty()) {
return $page->$field()->kt();
exit;
}
}
}
};
// $page->getImage('coverimage', 'cover')
page::$methods['getImage'] = function($page, $field, $class='') {
$image = $page->$field()->toFile();
if($image) {
$img = new Brick('img');
$img->attr('src', $image->url());
$img->attr('alt', $image->alt());
$figure = new Brick('figure');
$figure->addClass($class);
$figure->append($image);
return $figure;
} else {
return '';
}
};
//method to create a custom url
page::$methods['customeUrl'] = function($page) {
return site()->url() . '/something/' . $page->uid();
};
page::$methods['canonicalURL'] = function($page) {
return $page->url() . r(params(), '/') . kirby()->request()->params();
};
page::$methods['canonicalURL'] = function($page) {
return $page->url() . r(params() || $page->isHomePage(), '/') . kirby()->request()->params();
};
// pages methods
pages::$methods['onlyTranslated'] = function($pages) {
return $pages->filter(function($page) {
return $page->content(site()->language()->code())->exists();
});
};
// quick way to loop through a pages collection; usage: echo $pages->each('<p>Title: {title}</p>');
pages::$methods['each'] = function($pages, $string) {
preg_match_all('/\{(.+?)\}/', $string, $matches);
if(isset($matches[1])) {
$matches = array_flip($matches[1]);
$html = '';
foreach($pages as $p) {
$allowed = array_keys($p->content()->toArray());
array_walk($matches, function (&$value, $key) use ($p, $allowed) {
if(in_array($key, $allowed)){
return $value = $p->{$key}()->value();
}
}, $p);
$html .= str::template($string, $matches);
}
return $html;
}
};
/**
* Creates chunks of random size
*
* @param int $min Minimum number of items in chunk
* @param int $max Maximum number of items in chunk
* @return object A new collection with an item for each chunk and a subcollection in each chunk
* Usage:
* $projects = page('projects')->children()->shuffle();
* $max = mt_rand(1,$projects->count());
* $min = mt_rand(1, $max);
* $chunks = $projects->randomChunk($min,$max);
*/
pages::$methods['randomChunk'] = function($pages, $min, $max) {
$temp = clone $pages;
$chunks = [];
$size=1;
$min = (1 >= $min && $min <= $max) ? $min:1;
$max = $max <= $pages->count()? $max: $pages->count();
while ($temp->count() > 0) {
$size = mt_rand($min,$max);
array_push($chunks, array_splice($temp->data,0, $size));
}
$chunkCollections = [];
foreach($chunks as $items) {
$collection = clone $pages;
$collection->data = $items;
$chunkCollections[] = $collection;
}
// convert the array of chunks to a collection object
return new Collection($chunkCollections);
};
// files methods
// search in files (only works with Files object, i.e. $page->files(), not $page->children()->files() etc.)
// only works with Files object, i.e. $page->files(), not $page->children()->files() etc.
files::$methods['search'] = function($files, $query, $params = array()) {
if(is_string($params)) {
$params = array('fields' => str::split($params, '|'));
}
$defaults = array(
'minlength' => 2,
'fields' => array(),
'words' => false,
'score' => array()
);
$options = array_merge($defaults, $params);
$collection = clone $files;
$searchwords = preg_replace('/(\s)/u',',', $query);
$searchwords = str::split($searchwords, ',', $options['minlength']);
if(!empty($options['stopwords'])) {
$searchwords = array_diff($searchwords, $options['stopwords']);
}
if(empty($searchwords)) return $collection->limit(0);
$searchwords = array_map(function($value) use($options) {
return $options['words'] ? '\b' . preg_quote($value) . '\b' : preg_quote($value);
}, $searchwords);
$preg = '!(' . implode('|', $searchwords) . ')!i';
$results = $collection->filter(function($file) use($query, $searchwords, $preg, $options) {
$data = $file->meta()->toArray();
$keys = array_keys($data);
if(!empty($options['fields'])) {
$keys = array_intersect($keys, $options['fields']);
}
$file->searchHits = 0;
$file->searchScore = 0;
foreach($keys as $key) {
$score = a::get($options['score'], $key, 1);
// check for a match
if($matches = preg_match_all($preg, $data[$key], $r)) {
$file->searchHits += $matches;
$file->searchScore += $matches * $score;
// check for full matches
if($matches = preg_match_all('!' . preg_quote($query) . '!i', $data[$key], $r)) {
$file->searchScore += $matches * $score;
}
}
}
return $file->searchHits > 0 ? true : false;
});
$results = $results->sortBy('searchScore', SORT_DESC);
return $results;
};
// quick way to loop through images and create a figure tag for each, usage: $files->each('test');
files::$methods['each'] = function($files, $class=null, $alt=null, $caption=null) {
$html = '';
foreach($files as $file) {
$html .= kirbytag([
'image' => $file->url(),
'class' => $class,
'alt' => !is_null($alt)? $file->{$alt}()->value(): null,
'caption' => !is_null($caption)? $file->{$caption}()->value(): null,
]);
}
return $html;
};
// field methods
field::$methods['ktRaw'] = function($field) {
$text = $field->kirbytext();
return preg_replace('/(.*)<\/p>/', '$1', preg_replace('/<p>(.*)/', '$1', $text));
};
field::$methods['split'] = function($field) {
$string = $field->value();
$matches = preg_split('/([:!?.])/', $string, 2, PREG_SPLIT_DELIM_CAPTURE);
if(isset($matches[2]) && $matches[2] !== '') {
$title = '<strong>' . $matches[0] . $matches[1] . '</strong>' . $matches[2];
} else {
$title = '<strong>' . explode(' ', $string, 2)[0] . '</strong>' . ' ' . explode(' ', $string, 2)[1];
}
return $title;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment