
bytesource
Members-
Posts
220 -
Joined
-
Last visited
Everything posted by bytesource
-
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@soma I am sorry, there was a typo in my previous post. What I wanted to say is that I am only using FieldtypeTextLanguage and FieldtypeTextareaLanguage at the moment. When I echo the type of the field the hook is called on, I get both FieldtypeTextLanguage and FieldtypeTextareaLanguage as output. You are right about the fieldtypes: FieldtypeTextareaLanguage extends FieldtypeTextarea FieldtypeTextarea extends FieldtypeText Also, I actually made two hooks to cover both FieldtypeTextLanguage, and FieldtypeText (although I am not using FieldtypeText at this moment, but will later): $fieldClasses = array("FieldtypeTextLanguage", "FieldtypeText"); foreach ($fieldClasses as $class) { wire()->addHookAfter("$class::formatValue", null, function(HookEvent $event){ $value = $event->return; $value = str_replace(array("<p>","</p>"), "", $value); $event->return = $value; }); } Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
Hi, I only today realized that the following hook is not working fully as intended: wire()->addHookAfter("FieldtypeTextLanguage::formatValue", null, function($event){ $value = $event->return; $value = str_replace(array("<p>","</p>"), "", $value); $event->return = $value; }); It also gets called on FieldtypeTextareaLanguage (I am only using FieldtypeTextLanguage and FieldtypeTextareaLanguage). I verified by adding: echo $event->arguments("field")->type; inside the hook function. Does anyone know why this happens? Cheers, Stefan EDIT: Removed a typo: (I am only using FieldtypeText and FieldtypeTextarea) changed to: (I am only using FieldtypeTextLanguage and FieldtypeTextareaLanguage) -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@Soma Now everything is working! Thank you so much for your help and patience! Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@Soma I find your solution elegant - the one adding a second texformatter - because it accomplishes everything in a few lines of code. Also, I am thankful for every line of code that allows me to better understand the design of Processwire. As for my method hooking into TextformatterTextile::formatValue, I assumed that this was the one that was hookable. Thanks to your remark and Captain Hook's confirmation, I now know I should have hooked into FieldtypeText::formatValue. So this is the code I came up with: wire()->addHookAfter("FieldtypeTextLanguage::formatValue", function(HookEvent $event) { $value = $event->arguments("value"); // Remove paragraph tags on single line text fields. $value = str_replace(array("<p>","</p>"), "", $value); $event->return = $value; }); Unfortunately, I still don't get the intended output. What is returned is the completely unformatted text (including all Textile specific identifiers). EDIT: Returning the unformatted string indicates the hook is called before application of the Textile textformatter. Is there any way to make sure my hook gets called on the output of the Textile textformatter? Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@Soma Please don't get me wrong. Your solution is quite elegantt, and I probably will pick it over the hook approach. I extended the selector to make the function work on all text fields: foreach($fields->find("type=FieldtypeText|FieldtypeTextLanguage") as $f) { $f->textformatters = array("TextformatterTextile", "TextformatterPstripper"); // add textformatters $f->save(); } The only reason I choose to use a hook is because I wanted to become more conformable with this technique. As for the Textile module, I replaced the current format() function (code on Github) with formatValue(): public function formatValue($page, $field, &$value) { require_once($this->config->paths->TextformatterTextile . 'classTextile.php'); $textile = new Textile(); $value = $textile->TextileThis($value); } I am not sure why the after hook I added does not get called. The formatValue() function does indeed exist and the name of the class is TextformatterTextile. Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@Soma As in my case a single text field will never be wrapped in a paragraph, I like the idea of handling this case dynamically, instead of adding a second formatter to every field of type text. Thanks to your help this actually was not that complicated to accomplish. First I 'updated' the Textile module to use formatValue() instead of format(): public function formatValue($page, $field, &$value) { require_once($this->config->paths->TextformatterTextile . 'classTextile.php'); $textile = new Textile(); $value = $textile->TextileThis($value); } As formatValue() is hookable, I added the following hook to _init.php: templates/_init.php wire()->addHookAfter("TextformatterTextile::formatValue", function(HookEvent $event) { $field = $event->arguments("field"); $value = $event->arguments("value"); if($field->type == "Text" || $field->type == "TextLanguage") { // Remove paragraph tags on single line text fields. $value = str_replace(array("<p>","</p>"), "", $value); } }); There is one problem left, though. The after hook apparently does not get called. For example, placing an echo statement somewhere inside the function body does not yield any output. That's why I would be glad if you could point me in the right direction, even though you might prefer another solution to this formatting problem. Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
Hi Steve, As for me, typographic changes on single line text fields (Text and TextLanguage) mostly comprise of making a word bold or cursive. Sometimes I also include a <span> tag (%some word%) that holds a CSS class, to achieve a more custom styling. I have found that I never need a single line text to be wrapped in paragraph tags. However, I am not a web designer, so my use case might be a little bit unusual. Therefore I'd love to hear the opinion on this topic from someone more experienced than me. Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@netcarver I use the Textile module on both fields of type text and textfield: textfield: Multi-line/multi-paragraph. The output is (and should be) at least one paragraph, so no problem here with the paragraph tags. text: Single line, mainly used for headers (h1-h5). Enclosing the output in a paragraph interferes with the styling of the site. I know that I could just, e.g. for a h2 heading, write the text as h2. This is my main header But if I later wanted to change h2 to h3, I had to go through all occurrences of this field in the admin and carry out the change. That's why I would prefer Textile to not wrap the output of a (single line) text field into paragraph tags. This would allow me to write code like this: // some template file // field type: text // field name: header // content: Hello World! <h2><?php echo $page->header; ?></h2> // => <h2>Hello World!</h2> In case I later wanted to change h2 to h3, I only needed to make one small change in the template file. Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@soma I read your post I also read the code of TextformatterPstripper, and does indeed what I need. However, I wanted to be able to always just select one formatter for both text fields and textfield fields, and then remove the surrounding paragraph tags dynamically, based on the type of the field inside the module. I know, this might be a bit overkill for such a small problem, but at least I was forced to find a way to retrieve the type of a field. When I could not find a solution, I asked here in the forum. Thanks again for your suggestions. They really helped me a lot! Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@soma Thanks for your great advice! I guess I could also just copy the Textile code into my own module, replace the format function with formatValue and then retrieve the type of the field with $field->type. It's a bit late already, but I'll try tomorrow. Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@diogo What I really want to know the type of the field that calls the Textile textformatter. Do you know how I could accomplish this inside a module function? Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@diogo Thanks for your reply. Acually that is what I have been doing. I am using the Textile module on textfield fields and my own module on text fields. I just wanted to be able to make the selection dynamically, instead of having to manually choose one of the formatters whenever I create a new text/textfield field type. Also, I'd like to better understand inner workings of Processwire. So I am also asking this question out of curiosity. Cheers, Stefan -
Retrieve The Type of A Field From Inside A Module
bytesource replied to bytesource's topic in Module/Plugin Development
@adiran Thanks for your reply. To be honest, I don't quite understand the code you suggested. The selector "fieldUsingTextile" suggests I need to know the name of the field in advance, but what I want to accomplish is that whatever field calls the format function of this module (here is the complete code on Github) will get checked for its type. If the field type is FieldtypeText or TextLanguage, the surrounding paragraph tags are stripped, otherwise no further transformation is applied. All the Textile module does is calling the (official, I guess) Textile class, so this is probably where the additional paragraph tags are coming from. Cheers, Stefan -
Hi, I want to remove the surrounding paragraph tags, <p> and </p> from the output of the Textile text formatter, but only for associated fields of type text. The reason for this is that the additional paragraph tags often interfere with the page markup, e.g. when output inside header tags like this: //Text: "Hello World!" <h1><?php echo $page->fieldUsingTextile; ?></h1> // Output: // <h1><p>Hello World!</p><h1> The module code is short and easy to follow: public function format(&$str) { require_once($this->config->paths->TextformatterTextile . 'classTextile.php'); $textile = new Textile(); $str = $textile->TextileThis($str); } In order to strip out the surrounding paragraph tag, I added the following line at the bottom of the function: // Remove surrounding paragraph tags $str = preg_replace('/<p>(.*)<\/p>/', '$1', $str); The problem is that his code strips the outer paragraph tags for fields of type text and textfield. However, removing the outer paragraph tags on a possible multi-paragraph textfield does not make much sense and invalidates the HTML. So I need a way to say something like this: if (getFieldtype == 'Text' || getFieldtype == 'TextLanguage') { // remove paragraph tags as shown above } Any ideas are highly appreciated! Cheers, Stefan
-
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@Soma That is great news, indeed! Thanks a lot! Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@onjegolders Using a module to implement the unique number was a good opportunity for me to learn more about fieldtypes, not necessarily because it is the most straightforward solution. I really want to get to know the internals of Processwire better, but normally don't have enough time beside work to read up on the documentation. So I am actively looking for opportunities to implement something new. Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@adrian Necessary of not, I highly value best practices, so thanks a lot for this tip! Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@SiNNuT Thanks for pointing me to the Sanitizer class. Seeing the actual code makes understanding the functions much easier. I often use the cheatsheet, which is a godsend for learning the Processwire API, but wasn't familiar with $sanitizer yet. As for my code, I had to use wire('sanitizer)->pageName instead of $sanitizer->pageName. Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
For completeness I would like to add the final code I came up with. I decided to not only set the value of the title field, but also the value of the name field (called _pw_page_name internally). This is because the page name gets entered automatically as you type into the title field, but stays blank if the value of the title field is preset, thus causing an error when the page is saved. class FieldHelper extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array * */ public static function getModuleInfo() { return array( 'title' => 'FieldHelper', 'version' => 100, 'summary' => 'Hide fields depending on permission, role, or user.', 'singular' => true, 'autoload' => true ); } public function init() { // add before-hook to the inputfield render method $this->addHooKBefore("Inputfield::render", $this, "renderField"); } /** * Pre-fill certain fields if empty with unique identifier based on the page id * */ public function renderField(HookEvent $event) { // Get hold of an instance of the parent $parent_id = wire('input')->get->parent_id; $parent = wire('pages')->get($parent_id); $field = $event->object; $name = $field->name; $value = $field->value; // Only prefill the title field // for children of pages with template 'customer': if ($parent->template == 'customer') { if ($name == 'title' || $name == '_pw_page_name') { if ($value == '') { $presetValue = $this->uniqueValue(); if ($name == '_pw_page_name') { // URL-encode path name // http://php.net/manual/en/function.filter-var.php $presetValue = filter_var($presetValue, FILTER_SANITIZE_URL); } $field->set('value', $presetValue); } } } } public function uniqueValue() { $last_page_id = wire('pages')->get("include=all,sort=-id")->id; $id = date("Y") . "/" . ($last_page_id+1); // example for a possible id value return $id; } } Output in the admin on opening a new page: Title: 2013/1073 Name: 2013-1073 I am not sure if using filter_var($presetValue, FILTER_SANITIZE_URL) is the best way to sanitize the URL path name. Please let me know if there is a better or more idiomatic way. Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@host I got hit by the scope again! I guess I should finally start learning PHP from the ground up. Thanks a lot for your suggestion, the following code is indeed working: $parent_id = wire('input')->get->parent_id; echo "id: " . $parent_id; // => 1010 Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@kongondo I think it is still a GET parameter, in fact it has been right in front of me all the time: http://localhost/mysite/processwire/page/add/?parent_id=1010 However, in that case the following code should return 1010, but nothing is returned: $parent_id = $input->get->parent_id; echo $parent_id Could it be that there is something wrong with the above code syntactically? Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
@onjegolders I like your solution as it is simple and easy to implement. I am afraid, though, that it would not work in my case. My system is intended to handle both quotations and invoices, and quotations get deleted regularly. @adrian Thanks for the great advise. I wrote the following test code but $parent_id seems to not exist: class FieldHelper extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array * */ public static function getModuleInfo() { return array( 'title' => 'FieldHelper', 'version' => 100, 'summary' => 'Hide fields depending on permission, role, or user.', 'singular' => true, 'autoload' => true ); } public function init() { // add before-hook to the inputfield render method $this->addHooKBefore("Inputfield::render", $this, "renderField"); } public function renderField(HookEvent $event) { $parent_id = $input->get->parent_id; echo "id: " . $parent_id; // => id: // $parent = wire('pages')->get($parent_id); } } Out of curiosity: How can I find out about which variables are available at which time, e.g. how did you know what GET variables are passed around? Cheers, Stefan -
How to automatically set the value of a field?
bytesource replied to bytesource's topic in API & Templates
I have a follow up question. The title field should only be automatically set for pages with the template 'documents'. However, when adding a new page, there has not been a template attached yet. I then tried to identify a target page via the name of the template of its parent, but without having been saved to the database, there is no parent, either. So my question is: How can I get hold of an instance of a page that has not been saved yet? And what properties does such a page possess that I could use to determine if the title field should be set automatically? Cheers, Stefan -
Hi all, On my latest installation of Processwire 2.3 the fieldset options (fieldset_open, fieldset_open_END) are missing from the Add Field menu on the Edit Template page. The fieldset module is installed. I have another Processwire installation that I upgraded from version 2.2 to version 2.3, and there the fieldset option has always been present. Cheers, Stefan Edit: typos