Sort mixed models with one dataprovider using ArrayDataProvider - php

I used ArrayDataProvider to mix models and then merged them into one data-provider. I used the data-provider in grid-view and everything is works fine.
But I need to order the grid-view by one column I tried a lot of solutions but none of them are worked.
This my model code (order by item_order )
public function getAllSelectedItemsInTheUnit($unitId, $grid = false)
{
$finalList = array();
$storiesList = array();
$activityList = array();
$breakList = array();
$stories = UnitStories::find()->joinWith(['story'])->where("unit_id=$unitId")->all();
if (count($stories) > 0) {
foreach ($stories as $item) {
$storiesList[] = [
'key' => self::TYPE_STORY . $item->id,
'id' => $item->id,
'title' => $item->story->title,
'type' => self::TYPE_STORY,
'item_order' => $item->unit_order,
];
}
}
$activities = UnitActivities::find()->joinWith(['activity'])->where("unit_id=$unitId")->all();
if (count($activities) > 0) {
foreach ($activities as $item) {
$activityList[] = [
'key' => self::TYPE_ACTIVITY . $item->id,
'id' => $item->id,
'title' => $item->activity->title,
'type' => self::TYPE_ACTIVITY,
'item_order' => $item->activity_order,
];
}
}
$breaks = UnitBreaks::find()->where("unit_id=$unitId")->all();
if (count($breaks) > 0) {
foreach ($breaks as $item) {
$breakList[] = [
'key' => self::TYPE_BREAK . $item->id,
'id' => $item->id,
'title' => $item->title,
'type' => self::TYPE_BREAK,
'item_order' => $item->unit_order,
];
}
}
$finalList = array_merge($storiesList, $activityList, $breakList);
$dataProvider = new ArrayDataProvider([
'allModels' => $finalList, 'key' => 'key',
'sort' => [
'attributes' => ['item_order'],
],
]);
return $dataProvider;
}
Any solution will be very good even sort array by pure PHP I guess will fix the problem .

You can use usort()
usort($finalList, function ($a, $b) {
return $a['item_order'] < $b['item_order'];
});
Add your condition in callback >, <, <= etc

Related

Craft CMS element-api how to get values of a category field in entry

Working on an element-api.php file from a Craft CMS project. Has a lot of helper functions. I added a category called disciplines. I'm trying to expose the values for each entry.
Here's the whole helper function I'm working on:
// Get all projects, by date, newest first
function getAllProjects() {
$caseStudies = [];
$query = \craft\elements\Entry::find();
$query->section('caseStudies');
$query->orderBy('postDate desc');
foreach ($query->all() as $page) {
$isPublic = $page->public;
$parent = $page->getSection()->handle;
if ($isPublic) {
$serviceData = [];
foreach ($page->modules->all() as $module) {
switch ($module->type->handle) {
case 'service':
$service = $module->service->one();
if ($service) {
$serviceData[] = [
'id' => $service->service->one()->id,
'title' => $service->service->one()->title,
];
}
break;
}
}
$coverColor = [
'r' => $page->coverColor ? $page->coverColor->r : 0,
'g' => $page->coverColor ? $page->coverColor->g : 0,
'b' =>$page->coverColor ? $page->coverColor->b : 0,
];
$caseStudies[] = [
'id' => $page->id,
'title' => $page->title,
'meta' => [
'navigationColor' => $page->navigationColor->value,
'title' => $page->metaTitle ? $page->metaTitle : $page->title,
'description' => $page->metaDescription,
],
'slug' => $page->slug,
'postDate' => date("d-m-Y",$page->postDate->getTimestamp()),
'json' => UrlHelper::url("work/{$page->slug}.json"),
'parent' => $parent,
'headline' => $page->headline,
'client' => $parent === 'caseStudies' ? $page->client->one()->title : null,
'services' => $serviceData,
'discipline' => array_map(function (CategoryModel $category) {
return [
'id' => $category->id,
'title' => $category->title,
];
}, $page->discipline->find()),
'cover' => handelImages($page->cover->all()),
'coverColor' => $coverColor,
'coverVideo' => [
'source' => $page->coverVideo
]
];
}
}
return $caseStudies;
}
Everything works except in the caseStudies array I have added this line:
'discipline' => array_map(function (CategoryModel $category) {
return [
'id' => $category->id,
'title' => $category->title,
];
}, $page->discipline->find()),
which returns the error: Argument 1 passed to {closure}() must be an instance of CategoryModel, instance of craft\elements\Category given
site is at Craft 3.3.15. Element-Api plugin is 2.6.0
'dispiplines' => array_map('strval', $page->discipline->all())
This worked. Found a tag example right on the github page https://github.com/craftcms/element-api

Woocommerce rest api update product image gives error

I want to update my product with product image but it is not updated. I am using woocommerce rest API for adding a product.
I am following these step for update product:
Create a view file for display all the product list
Create edit function in the controller for getting all product data
when uploading a new image from edit form it gives an error
Here is my code:
if($request->hasfile('filename'))
{
foreach($request->file('filename') as $image)
{
$name=$image->getClientOriginalName();
$image->move('C:/xampp/htdocs/New-flex/wp-content/uploads/backend-product-image', $name);
$productimg_path_store_db = "http://localhost/New-flex/wp-content/uploads/backend-product-image/";
$productimg_allimg[] = $productimg_path_store_db.$name;
}
}
$AddContentText = $request->get('AddContentText');
if (!empty($AddContentText)) {
/* For List All product qnumber check in array */
$newallproducts_data = $woocommerce->get('products',array('per_page' => 100));
$array = json_decode(json_encode($newallproducts_data), True);
$partssku = array();
$partid = array();
$parturl = array();
foreach ($array as $key ) {
$partssku[] = $key['sku'];
$partid[] = $key['id'];
$parturl[] = $key['permalink'];
}
/* Create associative array product id and sku for compare */
$comb = array_combine($partssku,$partid);
/* Combine content QNUMBER and QTY in array */
$chunks = array_chunk(preg_split('/(;|,)/', $AddContentText), 2);
$result = array_combine(array_column($chunks, 0), array_column($chunks, 1));
/*Product qnumber allready avilabale array*/
$diff = array_intersect_key($result,$comb);
/*NEW PRODUCT array*/
$newproduct = array_diff($result, $diff);
/* Qnumber insert in database */
$parts_name = implode(',', array_keys($result));
/* count insert in database */
$noofpartsuse = implode(',', array_values($result));
/*echo "<pre>";
echo "main data";
print_r($result);
echo "allproduct array";
print_r($comb);
echo "Product qnumber allready avilabale";
print_r($diff);
echo "NEW PRODUCT";
print_r($newproduct);
echo "</pre>";*/
// print_r($newproduct_data);
//print_r($woocommerce->post('products', $data));
}
else{
$parts_name = '';
$noofpartsuse = '';
}
$productactive = $request->get('productactive');
if(!empty($productactive))
{
$productactive = "publish";
}
else{
$productactive = "draft";
}
$ProductListOrder = $request->get('ProductListOrder');
$producttype = $request->get('producttype');
$ProductQNumber = $request->get('ProductQNumber');
$ProductName = $request->get('name');
$ProductWidthMM = $request->get('ProductWidthMM');
$ProductLengthMM = $request->get('ProductLengthMM');
$ProductWidthInch = $request->get('ProductWidthInch');
$ProductLengthInch = $request->get('ProductLengthInch');
$Productinfotext = $request->get('Productinfotext');
$Producttechnocaldesc = $request->get('Producttechnocaldesc');
$metadescription = $request->get('metadescription');
$proimgalt = $request->get('proimg-alt');
$proyoutubelink = $request->get('proyoutubelink');
$proyoutubelinkalt = $request->get('proyoutubelink-alt');
$provimeolink = $request->get('provimeolink');
$provimeolinkalt = $request->get('provimeolink-alt');
$onshapelink = $request->get('onshapelink');
$onshapelinkalt = $request->get('onshapelink-alt');
$data = [
'name' => $ProductName,
'type' => $producttype,
'status' => $productactive,
'regular_price' => '',
'description' => $Productinfotext,
'short_description' => $Producttechnocaldesc,
'sku' => $ProductQNumber,
'categories' =>array (),
'meta_data' => [
[
'key' => 'list_order',
'value' => $ProductListOrder
],
[
'key' => 'ProductWidthMM',
'value' => $ProductWidthMM
],
[
'key' => 'ProductLengthMM',
'value' => $ProductLengthMM
],
[
'key' => 'ProductWidthInch',
'value' => $ProductWidthInch
],
[
'key' => 'ProductLengthInch',
'value' => $ProductLengthInch
],
[
'key' => 'proyoutubelink',
'value' => $proyoutubelink
],
[
'key' => 'proyoutubelink-alt',
'value' => $proyoutubelinkalt
],
[
'key' => 'provimeolink',
'value' => $provimeolink
],
[
'key' => 'provimeolink-alt',
'value' => $provimeolinkalt
],
[
'key' => 'onshapelink',
'value' => $onshapelink
],
[
'key' => 'onshapelink-alt',
'value' => $onshapelinkalt
],
[
'key' => 'UseParts-link',
'value' => $parts_name
],
[
'key' => 'Noofparts-use',
'value' => $noofpartsuse
]
],
'images' => array ()
];
/* image array for store image */
if(!empty($productimg_allimg)){
$images = &$data['images'];
$n = 0;
foreach($productimg_allimg as $id)
{
$images[] = array( //this array must be created dynamic
'src' => $id,
'position' => $n++
);
}
unset($images);
}
if(!empty($_POST['categories'])){
/* Producta category array */
$categories = &$data['categories'];
foreach($_POST['categories'] as $cat)
{
$categories[] = array( //this array must be created dynamic
'id' => $cat
);
}
unset($categories);
}
$data_insert = $woocommerce->post('products', $data);
if($data_insert){
foreach ($newproduct as $key => $value) {
$newproduct_data = [
'name' => $key,
'sku' => $key
];
$woocommerce->post('products', $newproduct_data);
}
}
return redirect('products')->with('success', 'Product has been Added');
Above code written in laravel

Using usort() on multidimensional alphanumeric array (numbers first)

Here is an example array I am attempting to sort:
$array = (object)array(
'this' => 'that',
'posts'=> array(
'title' => '001 Chair',
'title' => 'AC43 Table',
'title' => '0440 Recliner',
'title' => 'B419',
'title' => 'C10 Chair',
'title' => '320 Bed',
'title' => '0114'
),
'that' => 'this'
);
usort($array->posts, 'my_post_sort');
Here is the function I am using to sort:
function my_post_sort($a, $b) {
$akey = $a->title;
if (preg_match('/^[0-9]*$',$akey,$matches)) {
$akey = sprintf('%010d ',$matches[0]) . $akey;
}
$bkey = $b->title;
if (preg_match('/^[0-9]*$',$bkey,$matches)) {
$bkey = sprintf('%010d ',$matches[0]) . $bkey;
}
if ($akey == $bkey) {
return 0;
}
return ($akey > $bkey) ? -1 : 1;
}
This gives me the following results:
'posts', array(
'title' => 'C10 Chair',
'title' => 'B419',
'title' => 'AC43 Table',
'title' => '320 Bed',
'title' => '0440 Recliner',
'title' => '0114',
'title' => '001 Chair'
)
Now, the last step I need is getting the numbers to appear (descending) before the letters (descending).
Here is my desired output:
'posts', array(
'title' => '320 Bed',
'title' => '0440 Recliner',
'title' => '0114',
'title' => '001 Chair',
'title' => 'C10 Chair',
'title' => 'B419',
'title' => 'AC43'
)
I've tried all kinds of sorts, uasorts, preg_match, and other functions; and just cannot seem to figure out the last step.
Any suggestions or assistance? Thank you.
Try this comparing function:
function my_post_sort($a, $b) {
$akey = $a->title;
$bkey = $b->title;
$diga = preg_match("/^[0-9]/", $akey);
$digb = preg_match("/^[0-9]/", $bkey);
if($diga && !$digb) {
return -1;
}
if(!$diga && $digb) {
return 1;
}
return -strcmp($akey, $bkey);
}
It will sort in descending order, but place digits before other symbols.
First of all, I do not think your array can works... You can not have the same key many times on the same array level.
foreach ($array as $key => $title) {
if ( is_numeric(substr($title, 0, 1)) ) {
$new_array[$key] = $title;
}
}
array_multisort($array, SORT_DESC, SORT_STRING);
array_multisort($new_array, SORT_DESC, SORT_NUMERIC);
$sorted_array = array_merge($array, $new_array);

PHP - How to create such array?

The question is simple, I want to create the array below dynamically, but the code I got now only outputs the last row. Is there anybody who knows what is wrong with my dynamically array creation?
$workingArray = [];
$workingArray =
[
0 =>
[
'id' => 1,
'name' => 'Name1',
],
1 =>
[
'id' => 2,
'name' => 'Name2',
]
];
echo json_encode($workingArray);
/* My not working array */
$i = 0;
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
$i++;
}
}
echo json_encode($dynamicArray);
You dont need to have the $i stuff that is adding another level to your array that you dont want.
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray[] = ['id' => $key, 'name' => $value['options'];
}
}
echo json_encode($dynamicArray);
You are creating a new dynamic array at each iteration:
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
Instead, declare $dynamicArray = []; above the foreach, and then use:
array_push($dynamicArray, [ 'id' => $key, 'name' => $value['options']);
inside the array.

PHP - search in array and create new one

I want to avoid if it is possible foreach combined with if. I want to search the array, take out the matches and create new one base on result.
In this example I want to create separate arrays for each os -
$os1 = $array;
$os2 = $array...
Array looks like this:
$array = [
0 => [
'id' => 1,
'name' => 'name',
'os' => 1
],
1 => [
'id' => 2,
'name' => 'name',
'os' => 1
],
2 => [
'id' => 3,
'name' => 'name',
'os' => 2
],
3 => [
'id' => 3,
'name' => 'name',
'os' => 2
]
];
Use array_filter to reduce the input array to the expected result
$os = 1;
$data = array_filter($array, function($item) use ($os) {
return $item['os'] == $os;
});
The short one
$os1 = [];
$os2 = [];
$os3 = [];
foreach ($array as $item) {
${'os' . $item['os']}[] = array('id' => $item['id'], 'name' => $item[$name];
}
The better one
$os1 = [];
$os2 = [];
$os3 = [];
foreach ($array as $item) {
switch($item['os']) {
case 1:
$os1[] = array('id' => $item['id'], 'name' => $item[$name]);
break;
case 2:
$os2[] = array('id' => $item['id'], 'name' => $item[$name]);
break;
case 3:
$os3[] = array('id' => $item['id'], 'name' => $item[$name]);
break;
default:
throw new Exception('Unknown Os');
}
}
Also you maybe want to assign array($item['id'] => $item[$name]); instead of array('id' => $item['id'], 'name' => $item[$name]);
$os1 = [];
$os2 = [];
$os3 = [];
foreach ($array as $item) {
${'os' . $item['os']}[] = array($item['id'] => $item[$name]);
}

Categories