Jump to content

Understanding wakeupValue, sleepValue, sanitizeValue


Robin S
 Share

Recommended Posts

I'm working on a simple fieldtype module and trying to understand the wakeupValue, sleepValue and sanitizeValue methods a bit better. This and this have been helpful but I still have a few questions.

My module is for storing a reference to an image that is contained in one of the image fields in a page. I'm using a customised select inputfield to choose from the available images, and the reference to the image is stored in the database as a string in the form:

field_name|image_name

In the wakeupValue method I convert the reference string to an image object.

public function ___wakeupValue(Page $page, Field $field, $value) {
    list($field_name, $image_name) = explode("|", $value);
    $image = $page->$field_name->get("name=$image_name");
    return $image;
}

This is working fine, but at the moment I'm not doing anything in the sanitizeValue method. To get an idea of when sanitizeValue is called I have this...

public function sanitizeValue(Page $page, Field $field, $value) {
	$type = gettype($value);
	$log = wire("log");
	$log->save("debug", "Sanitized: $value, Type: $type");
	return $value;
}

...and it shows that for every Edit Page save in admin the sanitizeValue method receives both the image reference string and the image object.

Sanitized: photoxpress_8083749.jpg, Type: object

Sanitized: images_two|photoxpress_8083749.jpg, Type: string

Why does sanitizeValue get both these types? I can understand why the image object goes through sanitizeValue because I am setting that to the page, but why does the string go through sanitizeValue? I'm not setting the string to the page, just saving it to the database.

For modules like this that store data in a different type than they send to the page, will the sanitizeValue method always need to account for both variable types? That is, the method can't expect $value to always be a string or always an object - it will need to test the type of $value and apply different sanitizing checks accordingly?

And is this true for sleepValue also? Ryan said in another post:

sleepValue() does the opposite of wakeupValue() and translates a runtime value back to it's basic type for storage.

That makes sense if I was saving to my field via the API and set an image object to the field - sleepValue needs to convert the object to a reference string for storage in the database. But at the moment I'm only saving to the field via the admin, and so the $value received by sleepValue is a string coming from the inputfield, not an object. So to cover both bases I will need to test for the type of $value at the start of the sleepValue method?

I guess I'm asking if this is the normal/right way for such a module to work or if there is some better way to set it up so that sanitizeValue and sleepValue only have to handle one variable type.

  • Like 1
Link to comment
Share on other sites

Isn't the string you're seeing in the log from your inputfield, which you said to be setting a string currently?

Probably the sane way to handling the data would be that the runtime value is always the image obj. The sanitizeValue method will make sure any other valid (user) input, like the db string format, is converted to the runtime obj. sleepValue und wakeupValue will only handle the string to runtime obj conversion for both directions. 

  • Like 2
Link to comment
Share on other sites

Probably the sane way to handling the data would be that the runtime value is always the image obj. The sanitizeValue method will make sure any other valid (user) input, like the db string format, is converted to the runtime obj. sleepValue und wakeupValue will only handle the string to runtime obj conversion for both directions. 

Thanks, I've taken that advice and everything works great. Sanitizing to an image object means I avoid having to check for object vs. string in the sleepValue method.

For novice developers like myself I think it's a bit hard to grasp the sanitizeValue method because it's not obvious where the method is called. With some debugging it looks to me like sanitizeValue is called twice, with the flow being:

inputfield > sanitizeValue > sleepValue > database

and

database > wakeupValue > sanitizeValue > page

Is that correct? It's the first call that puzzles me a bit because the comment in Fieldtype.php for sanitizeValue says:

* Sanitize the value for runtime storage.

*

* This method should remove anything that's invalid from the given value. If it can't be sanitized, it should be blanked.

* This method filters every value set to a Page instance.

And I can't see where the "Page instance" comes into inputfield > sanitizeValue > sleepValue > database

@kixe

Thanks for directing me to your module - I haven't tried it before and it looks like it's very flexible.

It's not quite suitable for my purposes for a few reasons:

  • I want my select dropdown to include the images from all the image fields assigned to the template. Because each image field is a separate table in the database I don't think Fieldtype Select External Option will allow this.
  • I want to customise the select inputfield so it shows a thumbnail of the selected image (so it's easier for the user to select the image they want). I'm doing this by setting a thumbnail data attribute for each option in the options array. So my module needs to be something specific to images rather than Fieldtype Select External Option which has a broader application.
  • When used for image fields, it seems that the value saved by Fieldtype Select External Option is quite fragile. Because the option value has to be an integer you have to use the Sort column for the value. This means that if the images are reordered in the image field the image referenced by Fieldtype Select External Option is changed. For an image reference you really want the image name to be the value that is stored.

Also, I got some errors when attempting to install Fieldtype Select External Option. They are caused by the strings that are marked as translatable. I think lines like...

$f->label = _('Usage');

...need to be...

$f->label = $this->_('Usage');
  • Like 1
Link to comment
Share on other sites

Yeah the whole wakeup/sleepValue topic is a bit hidden in the code. Here's wakeupValue https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/core/Page.php#L605 and here's sleepValue (kinda) https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/core/Pages.php#L1252.

And sanitizeValue is always called when a value is set to the field, so it's also called when your inputfield's data are set to the field when saving the page.

  • Like 1
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...