So i try to make a hooking API like wordpress add_filter and apply_filters,
So this is my implementation
My problem is that apply_filters does not filter the hook
$hook = new Hook();
$hook->add_filter('filter',function($test) {
return ' stackoverflow';
});
$hook->add_filter('filter',function($test) {
return $test .' world';
},1);
echo $hook->apply_filters('filter','hello');
// Result is hello world
What's wrong with my code, I want to result like this
hello world stackoverflow
For adding filters
public function add_filter(string $tag,mixed $object,int $priority = 10,int $args_limit = 1): void
{
$hooks = static::$hooks;
if(isset($hooks[$tag])) {
static::$hooks[$tag]['sorted'] = false;
static::$hooks[$tag]['priority'][] = $priority;
static::$hooks[$tag]['object'][] = $object;
static::$hooks[$tag]['args_limit'][] = $args_limit;
} else {
static::$hooks[$tag] = [
'sorted' => true,
'priority' => [$priority],
'object' => [$object],
'args_limit' => [$args_limit]
];
}
}
and for applying the filters
public function apply_filters(string $tag,mixed $value,mixed ...$args): mixed
{
$hooks = static::$hooks;
// Shift value to args
array_unshift($args,$value);
$num_args = count($args);
if(isset($hooks[$tag])) {
$hooks = $hooks[$tag];
if(!$hooks['sorted']) {
// Sort filter by priority
array_multisort(
$hooks['priority'],
SORT_NUMERIC,
$hooks['object'],
$hooks['args_limit']
);
$hooks['sorted'] = true;
}
foreach($hooks['object'] as $key => $object) {
$args_limit = $hooks['args_limit'][$key];
if(0 === $args_limit) {
$value = call_user_func($object);
} elseif($args_limit >= $num_args) {
$value = call_user_func_array($object,$args);
} else {
// Slice arguments if not meet from the second statement
$value = call_user_func_array($object,array_slice($args,0,$args_limit));
}
}
}
return $value;
}
So I try to look wordpress core code but the too complicated.
Thanks
Finally solved it! , I just forgot that $value doesn't pass to the callbacks
Here's the fix, for future references
public function apply_filters(string $tag,mixed $value,mixed ...$args): mixed
{
$hooks = static::$hooks;
// +1 for $value parameter
$num_args = count($args) + 1;
if(isset($hooks[$tag])) {
$hooks = $hooks[$tag];
if(!$hooks['sorted']) {
// Sort filter by priority
array_multisort(
$hooks['priority'],
SORT_NUMERIC,
$hooks['object'],
$hooks['args_limit']
);
$hooks['sorted'] = true;
}
foreach($hooks['object'] as $key => $object) {
$args_limit = $hooks['args_limit'][$key];
if(0 === $args_limit) {
$value = call_user_func($object);
} elseif($args_limit >= $num_args) {
$value = call_user_func($object,$value,...$args);
} else {
// Slice arguments if not meet from the second statement
$slice = array_slice($args,0,$args_limit);
$value = call_user_func($object,$value,...$slice);
}
}
}
return $value;
}
I have two functions which appear to be slowing down PHP, and I believe its to do with the use of array_merge in the loops, only I am struggling to figure out how I can get around not doing so.
function fuseOzone($field) {
global $ozone;
if(isset($ozone['all'])) {
foreach($ozone['all'] as $priority => $functions) {
if(isset($ozone[$field][$priority])) {
$ozone[$field][$priority] = array_merge($ozone['all'][$priority], $ozone[$field][$priority]);
} else {
$ozone[$field][$priority] = array_merge($ozone['all'][$priority], array());
$ozone[$field][$priority] = array_unique($ozone[$field][$priority]);
}
}
}
if(isset($ozone[$field])) {
ksort($ozone[$field]);
}
}
function applyOzone($field, $content) {
global $ozone;
fuseOzone($field);
$args = array_slice(func_get_args(), 2);
if(isset($ozone[$field])) {
foreach($ozone[$field] as $priority => $functions) {
if(!is_null($functions)) {
foreach($functions as $function) {
if(!function_exists($function['function'])) {
continue;
}
$all_args = array_merge(array($content), $args);
$function_name = $function['function'];
$accepted_args = $function['accepted_args'];
if($accepted_args === 1) {
$the_args = array($content);
} elseif($accepted_args > 1) {
$the_args = array_slice($all_args, 0, $accepted_args);
} elseif($accepted_args === 0) {
$the_args = null;
} else {
$the_args = $all_args;
}
$content = call_user_func_array($function_name, $the_args);
}
}
}
}
return $content;
}
These functions are part of a larger class which essentially operates much like Wordpress actions. I.e. I can hook into a portion of content with filtering or such.
I want to minimize this by removing if else statement using simple code in laravel 5.5 can someone help me with it?
public function shirts($type='')
{
if($type == 'glass') {
$shirt = Product::where('category_id','1')->get();
$products = Category::find(1);
} elseif ($type == 'ic') {
$shirt = Product::where('category_id','2')->get();
$products = Category::find(2);
} elseif ($type == 'cover') {
$shirt = Product::where('category_id','3')->get();
$products = Category::findOrFail(3);
} else {
$shirt = Product::all();
}
return view('front.shirt',compact('products','shirt'));
}
One way would be to create a mappings for your type and comparing the type with the mappings.
public function shirts($type = '')
{
$type_mappings = [
'glass' => 1,
'ic' => 2,
'cover' => 3
];
if(array_key_exists($type, $type_mappings)) {
$shirt = Product::where('category_id', $type_mappings[$type])->get();
$products = Category::find($type_mappings[$type]);
} else {
$shirt = Product::all();
$products = null;
}
return view('front.shirt', compact('products', 'shirt'));
}
Edit : i assumed you want to avoid if else not as what the title of question says if still i am unclear please add comment so i can update the answer Thanks!
Lets handle it somewhere else as i guess your function only has the responsibility to find product based on id it get not mapping part so we can have something like :
// Your function with single responsibility to return product.
public function shirts($category = '')
{
$type = $this->CategoryIdMapper($category);
if($type == 0) {
$shirt = Product::all();
$products = null;
} else{
$shirt = Product::where('category_id',$type_id)->get();
$products = Category::findOrFail($type_id);
}
return view('front.shirt',compact('products','shirt'));
}
//let the mapping part be done by some independent function which you can later modify accordingly and independently.
public function CategoryIdMapper($category)
{
$categories = ['glass'=>1, 'ic'=> 2, 'cover' => 3 ];
if(array_key_exist($category,$categories))
{
return $categories[$category];
}
return 0;
}
I'm trying to load a website url from a textfile, then unset this string from an array and pick a random website from the array.
But once I try to access the array from my function the array would return NULL, does someone know where my mistake is located at?
My current code looks like the following:
<?php
$activeFile = 'activeSite.txt';
$sites = array(
'http://wwww.google.com',
'http://www.ebay.com',
'http://www.icloud.com',
'http://www.hackforums.net',
'http://www.randomsite.com'
);
function getActiveSite($file)
{
$activeSite = file_get_contents($file, true);
return $activeSite;
}
function unsetActiveSite($activeSite)
{
if(($key = array_search($activeSite, $sites)) !== false)
{
unset($sites[$key]);
return true;
}
else
{
return false;
}
}
function updateActiveSite($activeFile)
{
$activeWebsite = getActiveSite($activeFile);
if(!empty($activeWebsite))
{
$unsetActive = unsetActiveSite($activeWebsite);
if($unsetActive == true)
{
$randomSite = $sites[array_rand($sites)];
return $randomSite;
}
else
{
echo 'Could not unset the active website.';
}
}
else
{
echo $activeWebsite . ' did not contain any active website.';
}
}
$result = updateActiveSite($activeFile);
echo $result;
?>
$sites is not avaliable in unsetActiveSite function you need to create a function called "getSites" which return the $sites array and use it in unsetActiveSite
function getSites(){
$sites = [
'http://wwww.google.com',
'http://www.ebay.com',
'http://www.icloud.com',
'http://www.hackforums.net',
'http://www.randomsite.com'
];
return $sites;
}
function unsetActiveSite($activeSite)
{
$sites = getSites();
if(($key = array_search($activeSite, $sites)) !== false)
{
unset($sites[$key]);
return true;
}
else
{
return false;
}
}
Here is the scenario, and let me start off saying any help would be a god-send, I have cloned the Article Category module inside Joomla! Basically changed all the articles_category to breed_articles (for my purpose). This worked fine, where I am stuck at is where in the module code can I define a specific category to pull articles from.
I know I can do this in the backend but I am working on a dynamic way to pull articles by categories and need to define the category in the module code. That being said, I will also need to pull the categoies by the slug not id.
Where I have been looking is the helper.php file in the module and I believe that I am on the right path there. I have tried replacing a few things and tracing the code but I am not very familiar with Joomla!
helper.php
$com_path = JPATH_SITE.'/components/com_content/';
require_once $com_path.'router.php';
require_once $com_path.'helpers/route.php';
JModelLegacy::addIncludePath($com_path . '/models', 'ContentModel');
abstract class modBreedArticlesHelper
{
public static function getList(&$params)
{
// Get an instance of the generic articles model
$articles = JModelLegacy::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
// Set application parameters in model
$app = JFactory::getApplication();
$appParams = $app->getParams();
$articles->setState('params', $appParams);
// Set the filters based on the module params
$articles->setState('list.start', 0);
$articles->setState('list.limit', (int) $params->get('count', 0));
$articles->setState('filter.published', 1);
// Access filter
$access = !JComponentHelper::getParams('com_content')->get('show_noauth');
$authorised = JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id'));
$articles->setState('filter.access', $access);
// Prep for Normal or Dynamic Modes
$mode = $params->get('mode', 'normal');
switch ($mode)
{
case 'dynamic':
$option = $app->input->get('option');
$view = $app->input->get('view');
if ($option === 'com_content') {
switch($view)
{
case 'category':
$catids = array($app->input->getInt('id'));
break;
case 'categories':
$catids = array($app->input->getInt('id'));
break;
case 'article':
if ($params->get('show_on_article_page', 1)) {
$article_id = $app->input->getInt('id');
$catid = $app->input->getInt('catid');
if (!$catid) {
// Get an instance of the generic article model
$article = JModelLegacy::getInstance('Article', 'ContentModel', array('ignore_request' => true));
$article->setState('params', $appParams);
$article->setState('filter.published', 1);
$article->setState('article.id', (int) $article_id);
$item = $article->getItem();
$catids = array($item->catid);
}
else {
$catids = array($catid);
}
}
else {
// Return right away if show_on_article_page option is off
return;
}
break;
case 'featured':
default:
// Return right away if not on the category or article views
return;
}
}
else {
// Return right away if not on a com_content page
return;
}
break;
case 'normal':
default:
$catids = $params->get('catid');
$articles->setState('filter.category_id.include', (bool) $params->get('category_filtering_type', 1));
break;
}
// Category filter
if ($catids) {
if ($params->get('show_child_category_articles', 0) && (int) $params->get('levels', 0) > 0) {
// Get an instance of the generic categories model
$categories = JModelLegacy::getInstance('Categories', 'ContentModel', array('ignore_request' => true));
$categories->setState('params', $appParams);
$levels = $params->get('levels', 1) ? $params->get('levels', 1) : 9999;
$categories->setState('filter.get_children', $levels);
$categories->setState('filter.published', 1);
$categories->setState('filter.access', $access);
$additional_catids = array();
foreach($catids as $catid)
{
$categories->setState('filter.parentId', $catid);
$recursive = true;
$items = $categories->getItems($recursive);
if ($items)
{
foreach($items as $category)
{
$condition = (($category->level - $categories->getParent()->level) <= $levels);
if ($condition) {
$additional_catids[] = $category->id;
}
}
}
}
$catids = array_unique(array_merge($catids, $additional_catids));
}
$articles->setState('filter.category_id', $catids);
}
// Ordering
$articles->setState('list.ordering', $params->get('article_ordering', 'a.ordering'));
$articles->setState('list.direction', $params->get('article_ordering_direction', 'ASC'));
// New Parameters
$articles->setState('filter.featured', $params->get('show_front', 'show'));
$articles->setState('filter.author_id', $params->get('created_by', ""));
$articles->setState('filter.author_id.include', $params->get('author_filtering_type', 1));
$articles->setState('filter.author_alias', $params->get('created_by_alias', ""));
$articles->setState('filter.author_alias.include', $params->get('author_alias_filtering_type', 1));
$excluded_articles = $params->get('excluded_articles', '');
if ($excluded_articles) {
$excluded_articles = explode("\r\n", $excluded_articles);
$articles->setState('filter.article_id', $excluded_articles);
$articles->setState('filter.article_id.include', false); // Exclude
}
$date_filtering = $params->get('date_filtering', 'off');
if ($date_filtering !== 'off') {
$articles->setState('filter.date_filtering', $date_filtering);
$articles->setState('filter.date_field', $params->get('date_field', 'a.created'));
$articles->setState('filter.start_date_range', $params->get('start_date_range', '1000-01-01 00:00:00'));
$articles->setState('filter.end_date_range', $params->get('end_date_range', '9999-12-31 23:59:59'));
$articles->setState('filter.relative_date', $params->get('relative_date', 30));
}
// Filter by language
$articles->setState('filter.language', $app->getLanguageFilter());
$items = $articles->getItems();
// Display options
$show_date = $params->get('show_date', 0);
$show_date_field = $params->get('show_date_field', 'created');
$show_date_format = $params->get('show_date_format', 'Y-m-d H:i:s');
$show_category = $params->get('show_category', 0);
$show_hits = $params->get('show_hits', 0);
$show_author = $params->get('show_author', 0);
$show_introtext = $params->get('show_introtext', 0);
$introtext_limit = $params->get('introtext_limit', 100);
// Find current Article ID if on an article page
$option = $app->input->get('option');
$view = $app->input->get('view');
if ($option === 'com_content' && $view === 'article') {
$active_article_id = $app->input->getInt('id');
}
else {
$active_article_id = 0;
}
// Prepare data for display using display options
foreach ($items as &$item)
{
$item->slug = $item->id.':'.$item->alias;
$item->catslug = $item->catid ? $item->catid .':'.$item->category_alias : $item->catid;
if ($access || in_array($item->access, $authorised))
{
// We know that user has the privilege to view the article
$item->link = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug));
}
else
{
$app = JFactory::getApplication();
$menu = $app->getMenu();
$menuitems = $menu->getItems('link', 'index.php?option=com_users&view=login');
if (isset($menuitems[0]))
{
$Itemid = $menuitems[0]->id;
}
elseif ($app->input->getInt('Itemid') > 0)
{
// Use Itemid from requesting page only if there is no existing menu
$Itemid = $app->input->getInt('Itemid');
}
$item->link = JRoute::_('index.php?option=com_users&view=login&Itemid='.$Itemid);
}
// Used for styling the active article
$item->active = $item->id == $active_article_id ? 'active' : '';
$item->displayDate = '';
if ($show_date) {
$item->displayDate = JHTML::_('date', $item->$show_date_field, $show_date_format);
}
if ($item->catid) {
$item->displayCategoryLink = JRoute::_(ContentHelperRoute::getCategoryRoute($item->catid));
$item->displayCategoryTitle = $show_category ? ''.$item->category_title.'' : '';
}
else {
$item->displayCategoryTitle = $show_category ? $item->category_title : '';
}
$item->displayHits = $show_hits ? $item->hits : '';
$item->displayAuthorName = $show_author ? $item->author : '';
if ($show_introtext) {
$item->introtext = JHtml::_('content.prepare', $item->introtext, '', 'mod_articles_category.content');
$item->introtext = self::_cleanIntrotext($item->introtext);
}
$item->displayIntrotext = $show_introtext ? self::truncate($item->introtext, $introtext_limit) : '';
$item->displayReadmore = $item->alternative_readmore;
}
return $items;
}
public static function _cleanIntrotext($introtext)
{
$introtext = str_replace('<p>', ' ', $introtext);
$introtext = str_replace('</p>', ' ', $introtext);
$introtext = strip_tags($introtext, '<a><em><strong>');
$introtext = trim($introtext);
return $introtext;
}
/**
* Method to truncate introtext
*
* The goal is to get the proper length plain text string with as much of
* the html intact as possible with all tags properly closed.
*
* #param string $html The content of the introtext to be truncated
* #param integer $maxLength The maximum number of charactes to render
*
* #return string The truncated string
*/
public static function truncate($html, $maxLength = 0)
{
$baseLength = strlen($html);
$diffLength = 0;
// First get the plain text string. This is the rendered text we want to end up with.
$ptString = JHtml::_('string.truncate', $html, $maxLength, $noSplit = true, $allowHtml = false);
for ($maxLength; $maxLength < $baseLength;)
{
// Now get the string if we allow html.
$htmlString = JHtml::_('string.truncate', $html, $maxLength, $noSplit = true, $allowHtml = true);
// Now get the plain text from the html string.
$htmlStringToPtString = JHtml::_('string.truncate', $htmlString, $maxLength, $noSplit = true, $allowHtml = false);
// If the new plain text string matches the original plain text string we are done.
if ($ptString == $htmlStringToPtString)
{
return $htmlString;
}
// Get the number of html tag characters in the first $maxlength characters
$diffLength = strlen($ptString) - strlen($htmlStringToPtString);
// Set new $maxlength that adjusts for the html tags
$maxLength += $diffLength;
if ($baseLength <= $maxLength || $diffLength <= 0)
{
return $htmlString;
}
}
return $html;
}
public static function groupBy($list, $fieldName, $article_grouping_direction, $fieldNameToKeep = null)
{
$grouped = array();
if (!is_array($list)) {
if ($list == '') {
return $grouped;
}
$list = array($list);
}
foreach($list as $key => $item)
{
if (!isset($grouped[$item->$fieldName])) {
$grouped[$item->$fieldName] = array();
}
if (is_null($fieldNameToKeep)) {
$grouped[$item->$fieldName][$key] = $item;
}
else {
$grouped[$item->$fieldName][$key] = $item->$fieldNameToKeep;
}
unset($list[$key]);
}
$article_grouping_direction($grouped);
return $grouped;
}
public static function groupByDate($list, $type = 'year', $article_grouping_direction, $month_year_format = 'F Y')
{
$grouped = array();
if (!is_array($list)) {
if ($list == '') {
return $grouped;
}
$list = array($list);
}
foreach($list as $key => $item)
{
switch($type)
{
case 'month_year':
$month_year = JString::substr($item->created, 0, 7);
if (!isset($grouped[$month_year])) {
$grouped[$month_year] = array();
}
$grouped[$month_year][$key] = $item;
break;
case 'year':
default:
$year = JString::substr($item->created, 0, 4);
if (!isset($grouped[$year])) {
$grouped[$year] = array();
}
$grouped[$year][$key] = $item;
break;
}
unset($list[$key]);
}
$article_grouping_direction($grouped);
if ($type === 'month_year') {
foreach($grouped as $group => $items)
{
$date = new JDate($group);
$formatted_group = $date->format($month_year_format);
$grouped[$formatted_group] = $items;
unset($grouped[$group]);
}
}
return $grouped;
}
}
It looks like my issue was really specific to the project I am working on. If anyone happens to find this or wants to accomplish something similar, read on.
Decided to accomplish what I was doing using a JDatabase query. To retrieve the articles using the category alias, I queried the DB to match the alias I was giving the query to the category ID. Then joined the content table to get the article information.
All the information you need to make a proper JDatabase query can be found here: http://docs.joomla.org/Accessing_the_database_using_JDatabase