Jump to content

Detect changes made to repeater field


Harmen
 Share

Recommended Posts

Hi All,

I've made a previous regarding an issue which I solved but I stumbled across a new issue :). Below again the explanation needed.

You need a short introduction for this. The company I am working for has approx. 80 products on their website and they all have their own features. The features are imported from an older system which isn't used anymore. Back then, when they changed from the old system to PW, we imported the features into the product pages as a JSON-array so the pages could load a bit faster as exploding a JSON array is a bit faster than loading in a lot of items from a table or a repeater field.

How the JSON array looks like: 

{
    "2": { 										// The ID of the group that contains the actual features
        "name": "Model and function",			// The name of the group
        "features": {
            "43": {								// Attribute ID
                "name": "Resolution (DPI)",		// Attribute name
                "values": {						
                    "896": "500-1500-2000-3500" // Value ID and value name
                }
            }
        }
    }
}

Now we are adding a few more products to the catalog with new features and some that are already in use by other products but I am really struggling to assign the right ID's with the correct values in 7 different languages without messing up filters etc. So I decided to develop a module that lets you easily add feature groups, attributes and values as pages and connect these to the product using a repeater. This started by exporting all the current groups, attributes and values and import them as pages in the following structure:

- Features
	- Feature Groups
		- Group 1
		- Group 2
		- ...
	- Feature Attributes
		- Attribute 1
		- Attribute 2
		- ...
	- Feature Values
		- Value 1
		- Value 2
		- ...

Secondly, I created a repeater field that I assigned to the 'Features'-page that can handle the JSON structure explained above by seeing each item of the repeater field as a group. Inside each item you can select the group page and you will find another repeater which contains 2 page selectors to select an attribute and a value. A single repeater field looks like this:

756090769_Schermafbeelding2018-11-26om16_24_04.thumb.png.2407971d0fb8ac9830fcc492449c02ec.png

Next step was to create a module that gets this field as an Inputfield from the Features page. Once the user has finished adding groups, attributes and values he can click on save and I export all the values in the same JSON array structure as earlier but now the ID's of the groups, attributes and values are just the page ID's. This works great to add new features to new products. 

BUT, sometimes the features of a product change or need to be changed and you don't want to change the JSON array manually.

So my idea was to do the same thing as adding the features, but now you grab the values from the product first and populate the items of the repeater field.

$featuresPage = wire("pages")->get("template=features");
$featureGroups = json_decode($product->features, true);
foreach ($featureGroups as $featureGroupID => $featureGroup){
	$row = $featuresPage->features_repeater->getNewItem();
	$groupPage = wire("pages")->get($featureGroupID);
	$row->feature_group_selector = $groupPage;
	$row->save();
	foreach ($featureGroup["features"] as $featureID => $feature){
		$featuresRow = $row->feature_repeater->getNewItem();
		$attributePage = wire("pages")->get($featureID);
		$valuePage = wire("pages")->get(key($feature['values']));

		$featuresRow->feature_attribute_selector = $attributePage;
		$featuresRow->feature_value_selector = $valuePage;

		$featuresRow->save();
	}
	$row->save();
}
$featuresPage->save();

$f = wire('fields')->get('features_repeater');
$inputfield = $f->getInputfield($featuresPage);

$form->add($inputfield);

$f = $this->modules->get("InputfieldSubmit");
$f->name = 'updateFeatures';
$f->label = 'Update Features';
$f->icon = 'plus';
$f->value = 'Update Features';
$form->add($f);

Then the user can change / add features, click save and done!

It is possible to update the feature attributes and values, but when I change the feature group value, it seems like PW creates a new field behind the scenes and keeps the old value as well. So let's say I have the following feature structure:

- Feature Group 1
	- Feature attribute 1	- Feature value 1

Now I want to update Feature Group 1 to Feature Group 2, below is the desired result and the actual result:

// === Desired result
- Feature Group 2
	- Feature attribute 1	- Feature value 1
    
// === Actual result    
- Feature Group 2
	- Feature attribute 1	- Feature value 1
- Feature Group 1
	- Feature attribute 1	- Feature value 1

 

I am using the following function to update the features:

    private function processForm5_UpdateFeatures(InputfieldForm $form){
        $form->processInput($this->input->post);
        if (count($form->getErrors())) return false;

        $pageID = $this->session->selectedProduct;
        $product = wire('pages')->get($pageID);
        $product->of(false);

        $repeater = $form->get("features_repeater")->value;

        $languages = wire("languages");
        foreach ($languages as $language) {
            $return_array = [];
            $i = 0;
            foreach ($repeater as $repeaterItem) {
                //$this->message($repeaterItem);
                $group = $repeaterItem->feature_group_selector;

                if ($group["id"] == 0) {
                    continue;
                } else {
                    $group = wire("pages")->get($group["id"]);
                    $feature_group_name = &$return_array[$group->id]['name'];
                    if (!isset($feature_group_name)) $feature_group_name = $group->title->getLanguageValue($language);

                    $features = $repeaterItem->feature_repeater;

                    foreach ($features as $feature) {
                        $this->message($feature);
                        $attribute = $feature->feature_attribute_selector;
                        $value = $feature->feature_value_selector;

                        if ($attribute["id"] == 0 || $value["id"] == 0) {
                            continue;
                        } else {
                            $attribute = wire("pages")->get($attribute["id"]);
                            $value = wire("pages")->get($value["id"]);

                            $return_array[$group->id]['features'][$attribute->id]['name'] = $attribute->title->getLanguageValue($language);
                            $return_array[$group->id]['features'][$attribute->id]['values'][$value->id] = $value->title->getLanguageValue($language);
                        }
                    }
                }
            }
            $product->features->setLanguageValue($language->name, json_encode($return_array, JSON_UNESCAPED_UNICODE));
        }
        $product->save();

        $featuresPage = wire("pages")->get("template=features");
        $featuresPage->features_repeater->removeAll();
        $featuresPage->save();

/*        $this->messages("clear all");
        $this->errors("clear all");*/

        $this->message("Updated all features for {$product->title}");
        $this->session->redirect("../");

    }

Is there a way to avoid the current result and get the desired result? Why is there even a new repeater page created for the new value? Anything that can help me is greatly appreciated!

 

~Harmen

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...