I'm trying to get the shipping available methods by country code that giving in the request, in the above code I'm facing an issue/conflict
That the available locations can be both a country or a continent so I need to check if this country code is a part of some continent.
the problem is with the first zone I get all methods in all zones not just within the first ( the callback return ).
The second zone which has the continents/countries ( rest of the world ) I get no issues with it but as far I guess that's because its the end of the loop. ( as I have two zones for now )
add_action("rest_api_init", function () {
register_rest_route(
"test-api/v1",
"shipping-cost",
array(
'callback' => function ($req) {
$country_code = $req->get_param('country_code');
$quantity = $req->get_param('quantity');
$shipping_cost = 0;
$methodes = [];
if (class_exists('WC_Shipping_Zones')) {
$all_zones = WC_Shipping_Zones::get_zones();
if (!empty($all_zones)) {
foreach ($all_zones as $zone) {
if (!empty($zone['zone_locations'])) {
foreach ($zone['zone_locations'] as $location) {
$wc_contries = new WC_Countries();
$continent_code = $wc_contries->get_continent_code_for_country($country_code);
if ($country_code === $location->code || $continent_code === $location->code) {
if (!empty($zone['shipping_methods'])) {
$shipping_method_ctrl = new WC_REST_Shipping_Zone_Methods_Controller();
foreach ($zone['shipping_methods'] as $flat_rate) {
$shipping_method = $shipping_method_ctrl->prepare_item_for_response($flat_rate, $req);
$methodes[] = (object) $shipping_method;
}
}
}
}
}
}
}
}
return $methodes;
}
)
);
});
Here's the answer: ( adding break with the number of the array want it to be stop )
Register_rest_route(
"kefan-api/v1",
"shipping-cost",
array(
'callback' => function ($req) {
$country_code = $req->get_param('country_code');
$methodes = [];
if (class_exists('WC_Shipping_Zones')) {
$all_zones = WC_Shipping_Zones::get_zones();
if (!empty($all_zones)) {
foreach ($all_zones as $zone) {
if (!empty($zone['zone_locations'])) {
foreach ($zone['zone_locations'] as $location) {
$wc_contries = new WC_Countries();
$continent_code = $wc_contries->get_continent_code_for_country($country_code);
if ($country_code === $location->code || $continent_code === $location->code) {
if (!empty($zone['shipping_methods'])) {
$shipping_method_ctrl = new WC_REST_Shipping_Zone_Methods_Controller();
foreach ($zone['shipping_methods'] as $flat_rate) {
$shipping_method = $shipping_method_ctrl->prepare_item_for_response($flat_rate, $req);
$methodes[] = (object) $shipping_method;
}
break 2;
}
}
}
}
}
}
}
return $methodes;
}
)
);
Related
I have navigation which looks like this in the system:
At the moment, I am able to print an array of objects containing the menu items recursively, and the code looks like this:
public function get() {
$current_path = \Drupal::service('path.current')->getPath();
$path_items = explode ('/',$current_path);
$menu_array = [];
$menu = $path_items[4];
if(!empty ($menu) ){
$sub_nav = \Drupal::menuTree()->load($menu, new \Drupal\Core\Menu\MenuTreeParameters());
foreach($sub_nav as $nav){
array_push($menu_array, $nav);
}
$manipulators = array(
array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
);
$sub_nav = \Drupal::menuTree()->transform($sub_nav, $manipulators);
$this->generateSubMenuTree($menu_array, $sub_nav);
$response = array_values($menu_array);
}
return (new ResourceResponse($response))->addCacheableDependency(array('#cache' => array('max-age' => 0)));
}
private function generateSubMenuTree(&$output, &$input, $parent = FALSE) {
$input = array_values($input);
$items = 0;
foreach($input as $key => $item) {
//If menu element disabled skip this branch
if ($item->link->isEnabled()) {
if ($item->link instanceof \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent) {
$uuid = $item->link->getDerivativeId();
$entity = \Drupal::service('entity.repository')
->loadEntityByUuid('menu_link_content', $uuid);
}
$link_data['name'] = $item->link->getTitle();
if(!empty($item->link->pluginDefinition['url'])){
$link_data['href'] = $item->link->pluginDefinition['url'];
}
//If not root element, add as child
if ($parent === FALSE) {
$output[$key] = $link_data;
} else {
$output['children'][$key] = $link_data;
}
if ($item->hasChildren) {
if ($item->depth == 1) {
$this->generateSubMenuTree($output[$key], $item->subtree, $key);
} else {
$this->generateSubMenuTree($output['children'][$key], $item->subtree, $key);
}
}
$items ++;
}
}
}
The code above results into the following:
However my specification now changed in the sense that for Nav Data and Departments, I should only start including from the child elements onwards.
The result should be something like this:
{
[
{
name : "Shop"
children : [
{
name : "Promotions"
tabletColumn : 0
desktopColumn : 0
children : [...] 3 items
},
{ ... }
]
},
{...}
],
[
{
name : "Personal"
children : [...] 0 items
selected : true
}
],
{...}
{...}
}
Have been struggling with this logic for 24 hours already.
i want to create scope , but dont know how to create it because my code kinda kinky :d, code will be below. Can you show me example for my 1-2 sort requests which will work with search too? (i want to get this). Basic functional is like this -> i have searching form, which is searching between countries, also i can sort this countries by arrow buttons, by desc or asc, (first one is by country names sorting, and others is only numbers), im able now to sort correctly, and also search and then sort.
CONTROLLER :
$countries = Country::latest()->filter(request(['search']))->get();
$infos = Info::all();
$page = request('page');
$confirmed = Info::sum('confirmed');
$recovered = Info::sum('recovered');
$deaths = Info::sum('deaths');
//for by country name sorting
if (request()->get('sort') === 'country_desc')
{
$countries = Country::orderByDesc(Info::select('country')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderByDesc(Info::select('country')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
if (request()->get('sort') === 'country_asc')
{
$countries = Country::orderBy(Info::select('country')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderBy(Info::select('country')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
// for new cases sorting
if (request()->get('sort') === 'cases_desc')
{
$countries = Country::orderByDesc(Info::select('confirmed')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderByDesc(Info::select('confirmed')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
if (request()->get('sort') === 'cases_asc')
{
$countries = Country::orderBy(Info::select('confirmed')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderBy(Info::select('confirmed')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
// for deaths sorting
if (request()->get('sort') === 'deaths_desc')
{
$countries = Country::orderByDesc(Info::select('deaths')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderByDesc(Info::select('deaths')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
if (request()->get('sort') === 'deaths_asc')
{
$countries = Country::orderBy(Info::select('deaths')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderBy(Info::select('deaths')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
//for recovered sorting
if (request()->get('sort') === 'recovered_desc')
{
$countries = Country::orderByDesc(Info::select('recovered')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderByDesc(Info::select('recovered')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
if (request()->get('sort') === 'recovered_asc')
{
$countries = Country::orderBy(Info::select('recovered')->whereColumn('infos.country_id', 'countries.id'))->get();
if (request()->get('search'))
{
$countries = Country::orderBy(Info::select('recovered')->whereColumn('infos.country_id', 'countries.id'))
->latest()->filter(request(['search']))->get();
}
}
COUNTRY MODEL SCOPE :
public function scopeFilter($query, array $filters)
{
$query->when($filters['search'] ?? false, fn ($query, $search) => $query
->where('name', 'like', '%' . $search . '%'));
}
as you can see its kinda big code, so i want to create scopes or etc.. what is the best way to reduce this code
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 count the rows based on like and unlike value in an array.I want to count the rows based on like and unlike value.I need to display like:3 and unlike:1.Now it display like:0,unlike:0 '$content' value is either {"userid":"1","like":"1"} or {"userid":"1","unlike":"1"}
$like_count = 0;
$unlike_count = 0;
while($like_fet = mysql_fetch_assoc($query))
{
$content = $like_fet['CONTENT_VALUE'];
$datas = json_decode($content);
foreach($datas as $item)
{
$like = $item['like'];
$unlike = $item['unlike'];
if($like != '' && $unlike == '')
{
echo "like";
$like_count++;
}
if($unlike != '' && $like == '')
{
echo "unlike";
$unlike_count++;
}
}
}
$like_count=0;
$unlike_count=0;
while($like_fet=mysql_fetch_assoc($query)) {
$json = json_decode($like_fet['CONTENT_VALUE'], true);
if ( isset($json['like']) ) {
$like_count += $json['like'];
}
if ( isset($json['unlike']) ) {
$unlike_count += $json['unlike'];
}
}
depending on how CONTENT_VALUE actually works this can probably simplified to
$like_count=0;
$unlike_count=0;
while($like_fet=mysql_fetch_assoc($query)) {
$json = json_decode($like_fet['CONTENT_VALUE'], true);
if ( isset($json['like']) ) {
$like_count++;
}
else if ( isset($json['unlike']) ) {
$unlike_count++;
}
else {
trigger_error('CONTENT_VALUE without like/unlike element', E_USER_NOTICE);
}
}