Jump to content


  • Posts

  • Joined

Everything posted by suntrop

  1. Thanks guys! @bernhard That is quite nice, to add the second field by JS. I was thinking of adding it via PW's hook system and do the conversion in PHP. But I like your idea. Had to change some parts, because sometimes the field is inside a repeater field and the names are price_repeater1234. Perhaps it is just me, but I would have thought conditional hooks take this into account. I had to remove the Inputfield(name=price) and check from within the hook. BTW, there is a new str_starts_with() function in PHP 8 ? @MarkE Looks interesting! Like the idea a lot. This time I'll stick with the simpler help of JS.
  2. Hello everybody ? I am in need of some form of advice or ideas. I've got a site that displays products along with prices. Prices stored in net, but showed on the frontend and newsletter as its gross value. We decided to use net because there are three different gross values (different countries, calculated via external API) and it makes programming easier. So, now, my client wishes to input the gross value into the CMS. That would cause a lot of changes, (it is error-prone) and makes some things more difficult at our end of the product. Despite I'd like to give my clients what they need, I was thinking to use hooks for that. So whenever something is put into the field "price" will get converted before storing in the DB and vice versa gets converted to be shown as gross in the field value. That way, I "just" have to change it at a single point: the hook for the CMS field. What you think? Is this kind of more a hacky way and brings in the long run more problems than short benefits? I am always used to work with what I actually have and see :-)
  3. Hi all the password reset isn't working correctly. When I enter the username, I receive the reset email/link https://www.example.com/memberarea/login/?forgot=1&u=1222&t=nKIvd6Rpin4El.3Jc19aTPsDWAaZhw%2F9 But when I click the link I get redirected to the actual login page. The URL is https://www.example.com/memberarea/login/ again, there is no notification/error message and nothing to put in the verification code or reset the password. I just checked there is no redirect on behalf of my site/code. Found another forum thread and github issue with the same effect, but without any solution. PHP 7.4 PW 3.0.165 Login/Register 0.0.2 ProcessForgotPassword 1.0.3 Using it on frontend login, not admin login page
  4. Yeah, I did this. That's why I know there are 30 addresses that are not unique ?
  5. I have updated to PW 3.0.184 last weekend. Noticed this week, Mail-Login is not working any more. I guess there must be changes made in core or the Login module (had something ~3.0.164 before). The Login module says now, "To use email login, you must enable the “unique” setting for your email field." When I enable the checkbox "Unique" and save the "email" field, the checkbox is cleared again. There is no error message. But it is probably because there are already 30 email addresses more than once used. Problem now: It would be quite hard to check which accounts are the latest/active ones and which could be renamed or whatever. Anybody with an idea? Anyone knows when things changed in the Login module?
  6. Yes, I had set the namespace properly. Strange part now, I installed another PW instance, a couple of hours ago, and first thing I tested was the Functions API in a newly created _main.php. It worked. I did a lot of testing and lastly just copied the file itself. That file worked (was just an echo page()->id). I copied the markup again and everything was like before, but it now works. I have no idea what was wrong with the other file. Just tested with different encodings, BOM, w/out namespace etc. but nothing to reproduce the error.
  7. It is quite some time since I launched my last PW project and can't remember/find if I forgot something. The functions API in my /site/config.php is set to true. I have just installed a blank new PW project. But every call ends with an error. <?= var_dump($config->useFunctionsAPI); page()->get('title'); ?> bool(true) Darn… Fatal Error: Uncaught Error: Call to undefined function page() in site/templates/_main.php:15 The config setting is correct, but still it is not working. Did I miss something? I just installed 3.0.165 Edit: Just noticed it works fine in template files like basic-page.php and home.php but not in _main.php (which gets appended)
  8. Yes, can confirm and I had disabled 16A Just upgraded to current dev version. It got kind of worse. When I save a page with the pagename "teßtpage" the field is empty after admin page reloads. DB has a wrong punycode of "xn-stseite". However, saving "testsäite" will save but still results in a 404.
  9. BTW: it doesn't work with page URL either. I can create/save a page with name like teßtpage but get a 404 here as well. So it doesn't seem to be URL segments problem only I am using pW 3.0.165
  10. Yes, but nothing changed. Once there is any non ascii character I get a 404.
  11. I can't remember I have used this before. Especially for URL segments. But the website uses a lot of image tags. Unfortunately tags are saved as simple strings not with slugs alongside.
  12. Yes, I am speaking of Umlauts like äöü and ß. I did enable UTF8 page names and the whitelist contains all chars I need. However, it still shows a 404 for pages containing special chars.
  13. I am using images tags as links and some tags contain special characters (like schwarzweiß). Links are pointing to a URL segment. Problem is, URL with special chars are not working. I added $config->pageNameCharset = 'UTF8'; in my config file but still I see a 404 on URL with special chars. Any idea?
  14. Ok, but that is not what I am looking for. I'd like to keep it in one field. But I guess I'll revert everything to where I had just two textarea fields. That wasn't good to validate, but it worked.
  15. Thanks, but I don't get what you are trying to say. I need to have two separate addresses, because shipping is mostly other than billing address. But I still can't see how PW works exactly saving data. First PW calls sanitizeValue() and next calls sleepValue(). But when I check $value in sleepValue() $sleepValue = [ 'data_billing_company' => isset($value->billing_company) ? $value->billing_company : $page->billing_company, //… 'data_shipping_gender' => isset($value->shipping_gender) ? $value->shipping_gender : $page->shipping_gender, ]; it doesn't work either. Seems to be all $value->xxx are always set, even when not set when saving data from API.
  16. I created a custom fieldtype to store two addresses. It receives its data from a custom form and will later use it in a PDF. However, the problem is, users can save billing and shipping address separately with two slightly different frontend forms. When I save one form only data saved by this from will be saved, all other fields get deleted. So if the user saves his shipping address all billing fields are empty after the page is saved. First version of my fieldtype only had two textarea fields and everything worked fine. But now changed to have more control over every data field (name, street, etc.). I started from copying the Dimension fieldtype, which was a copy of the MapMaker fieldtype I guess. Problem should be inside Address::set() or the ___sleepValue() // Frontend form to save billing address $p->of(false); $p->address->billing_gender = sanitizer()->string( input()->post('gender') ); $p->address->billing_firstname = sanitizer()->string( input()->post('first_name') ); $p->address->billing_lastname = sanitizer()->string( input()->post('last_name') ); $p->address->billing_street = sanitizer()->string( input()->post('street') ); $p->address->billing_zipcode = sanitizer()->string( input()->post('zipcode') ); $p->address->billing_city = sanitizer()->string( input()->post('city') ); $p->address->billing_company = sanitizer()->string( input()->post('company') ); $p->address->billing_vatid = sanitizer()->string( input()->post('vatid') ); $p->address->billing_country = sanitizer()->int( input()->post('country') ); $save = $p->save('address'); <?php namespace ProcessWire; /** * ProcessWire Address Fieldtype * */ class FieldtypeAddress extends Fieldtype { /** * Initialize this Fieldtype * */ public function init() { parent::init(); } /** * get Inputfield for this fieldtype, set config attributes so they can be used in the inputfield * */ public function getInputfield(Page $page, Field $field) { $address = $this->modules->get('InputfieldAddress'); return $address; } /** * Get the database schema for this field * * @param Field $field In case it's needed for the schema, but usually should not. * @return array */ public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'TEXT NOT NULL'; // user last name $schema['data_billing_firstname'] = 'TEXT NOT NULL'; $schema['data_billing_gender'] = 'TEXT NOT NULL'; $schema['data_billing_company'] = 'TEXT NOT NULL'; $schema['data_billing_vatid'] = 'TEXT NOT NULL'; $schema['data_billing_street'] = 'TEXT NOT NULL'; $schema['data_billing_zipcode'] = 'TEXT NOT NULL'; $schema['data_billing_city'] = 'TEXT NOT NULL'; $schema['data_billing_country'] = 'TEXT NOT NULL'; $schema['data_shipping_lastname'] = 'TEXT NOT NULL'; $schema['data_shipping_firstname'] = 'TEXT NOT NULL'; $schema['data_shipping_company'] = 'TEXT NOT NULL'; $schema['data_shipping_street'] = 'TEXT NOT NULL'; $schema['data_shipping_zipcode'] = 'TEXT NOT NULL'; $schema['data_shipping_city'] = 'TEXT NOT NULL'; $schema['data_shipping_country'] = 'TEXT NOT NULL'; $schema['data_shipping_department']= 'TEXT NOT NULL'; $schema['data_shipping_gender'] = 'TEXT NOT NULL'; // Remove index from data column unset($schema['keys']['data']); return $schema; } /** * Any value will get sanitized before setting it to a page object * and before saving the data * */ public function sanitizeValue(Page $page, Field $field, $value) { if(!$value instanceof Address) $value = $this->getBlankValue($page, $field); if ( $value->isChanged('billing_company') || $value->isChanged('billing_gender') || $value->isChanged('billing_vatid') || $value->isChanged('billing_firstname') || $value->isChanged('billing_lastname') || $value->isChanged('billing_street') || $value->isChanged('billing_zipcode') || $value->isChanged('billing_city') || $value->isChanged('billing_country') || $value->isChanged('shipping_company') || $value->isChanged('shipping_firstname') || $value->isChanged('shipping_lastname') || $value->isChanged('shipping_street') || $value->isChanged('shipping_zipcode') || $value->isChanged('shipping_city') || $value->isChanged('shipping_country') || $value->isChanged('shipping_department') || $value->isChanged('shipping_gender') ) { $page->trackChange($field->name); } return $value; } /** * Get raw data values from database and perhaps adjust data for $page output * */ public function ___wakeupValue(Page $page, Field $field, $value) { if(empty($value) ) return false; // get blank $address = $this->getBlankValue($page, $field); // TODO: required? $country = $this->pages()->get( (int)$value['data_billing_country'] ); $address->billing = WireArray::new([ 'gender' => (string)$value['data_billing_gender'], 'company' => (string)$value['data_billing_company'], 'vatid' => (string)$value['data_billing_vatid'], 'first_name' => (string)$value['data_billing_firstname'], 'last_name' => (string)$value['data'], 'street' => (string)$value['data_billing_street'], 'zipcode' => (string)$value['data_billing_zipcode'], 'city' => (string)$value['data_billing_city'], 'country' => $country, 'block' => (string)$value['data_billing_company'] . PHP_EOL . (string)$value['data_billing_firstname'] . ' ' . (string)$value['data'] . PHP_EOL . (string)$value['data_billing_street'] . PHP_EOL . (string)$value['data_billing_zipcode'] . ' ' . (string)$value['data_billing_city'] . PHP_EOL . (string)$country->title, ]); $country = $this->pages()->get( (int)$value['data_shipping_country'] ); $address->shipping = WireArray::new([ 'gender' => (string)$value['data_shipping_gender'], 'company' => (string)$value['data_shipping_company'], 'department' => (string)$value['data_shipping_department'], 'first_name' => (string)$value['data_shipping_firstname'], 'last_name' => (string)$value['data_shipping_lastname'], 'street' => (string)$value['data_shipping_street'], 'zipcode' => (string)$value['data_shipping_zipcode'], 'city' => (string)$value['data_shipping_city'], 'country' => $country, 'block' => (string)$value['data_shipping_company'] . PHP_EOL . (string)$value['data_shipping_firstname'] . ' ' . (string)$value['data_shipping_lastname'] . PHP_EOL . (string)$value['data_shipping_street'] . PHP_EOL . (string)$value['data_shipping_zipcode'] . ' ' . (string)$value['data_shipping_city'] . PHP_EOL . (string)$country->title, ]); return $address; } /** * Get data from $page and adjust data for storing in database * */ public function ___sleepValue(Page $page, Field $field, $value) { // throw error if value is not of the right type if(!$value instanceof Address) throw new WireException('Expecting an instance of Address'); $sleepValue = [ 'data_billing_company' => (string)$value->billing_company, 'data_billing_vatid' => (string)$value->billing_vatid, 'data_billing_gender' => (string)$value->billing_gender, 'data_billing_firstname' => (string)$value->billing_firstname, 'data' => (string)$value->billing_lastname, 'data_billing_street' => (string)$value->billing_street, 'data_billing_zipcode' => (string)$value->billing_zipcode, 'data_billing_city' => (string)$value->billing_city, 'data_billing_country' => (string)$value->billing_country, 'data_shipping_company' => (string)$value->shipping_company, 'data_shipping_firstname' => (string)$value->shipping_firstname, 'data_shipping_lastname' => (string)$value->shipping_lastname, 'data_shipping_street' => (string)$value->shipping_street, 'data_shipping_zipcode' => (string)$value->shipping_zipcode, 'data_shipping_city' => (string)$value->shipping_city, 'data_shipping_country' => (string)$value->shipping_country, 'data_shipping_department' => (string)$value->shipping_department, 'data_shipping_gender' => (string)$value->shipping_gender, ]; return $sleepValue; } /** * Format value for output * */ public function ___formatValue(Page $page, Field $field, $value) { return $value; } /** * * Add mapping to different name for use in page selectors * This enables us to use it like "field.min=10, field.max<=200, field.graduation>10" */ public function getMatchQuery($query, $table, $subfield, $operator, $value) { if ($subfield == 'billing_company') $subfield = 'data_billing_company'; if ($subfield == 'billing_gender') $subfield = 'data_billing_gender'; if ($subfield == 'billing_vatid') $subfield = 'data_billing_vatid'; if ($subfield == 'billing_firstname') $subfield = 'data_billing_firstname'; if ($subfield == 'billing_lastname') $subfield = 'data'; if ($subfield == 'billing_street') $subfield = 'data_billing_street'; if ($subfield == 'billing_zipcode') $subfield = 'data_billing_zipcode'; if ($subfield == 'billing_city') $subfield = 'data_billing_city'; if ($subfield == 'billing_country') $subfield = 'data_billing_country'; if ($subfield == 'shipping_company') $subfield = 'data_shipping_company'; if ($subfield == 'shipping_firstname') $subfield = 'data_shipping_firstname'; if ($subfield == 'shipping_lastname') $subfield = 'data_shipping_lastname'; if ($subfield == 'shipping_street') $subfield = 'data_shipping_street'; if ($subfield == 'shipping_zipcode') $subfield = 'data_shipping_zipcode'; if ($subfield == 'shipping_city') $subfield = 'data_shipping_city'; if ($subfield == 'shipping_country') $subfield = 'data_shipping_country'; if ($subfield == 'shipping_department') $subfield = 'data_shipping_department'; if ($subfield == 'shipping_gender') $subfield = 'data_shipping_gender'; return parent::getMatchQuery($query, $table, $subfield, $operator, $value); } /** * there's none compatible * */ public function ___getCompatibleFieldtypes(Field $field) { return null; } /** * blank value is an WireData object Address * */ public function getBlankValue(Page $page, Field $field) { return new Address(); } /** * Get any inputfields used for configuration of this Fieldtype. * * This is in addition any configuration fields supplied by the parent Inputfield. * * @param Field $field * @return InputfieldWrapper * */ public function ___getConfigInputfields(Field $field) { $inputfields = parent::___getConfigInputfields($field); // nothing yet return $inputfields; } } /** * Helper WireData Class to hold an address object * */ class Address extends WireData { public function __construct() { // bd('address construct'); // $this->set('billing_company', null); // $this->set('billing_gender', null); // $this->set('billing_vatid', null); // $this->set('billing_firstname', null); // $this->set('billing_lastname', null); // $this->set('billing_street', null); // $this->set('billing_zipcode', null); // $this->set('billing_city', null); // $this->set('billing_country', null); // $this->set('shipping_company', null); // $this->set('shipping_firstname', null); // $this->set('shipping_lastname', null); // $this->set('shipping_street', null); // $this->set('shipping_zipcode', null); // $this->set('shipping_city', null); // $this->set('shipping_country', null); // $this->set('shipping_department', null); // $this->set('shipping_gender', null); } public function set($key, $value) { bd('VALUE: '.$value, 'address set: ' . $key ); // if ( // $key == 'billing_company' || // $key == 'billing_gender' || // $key == 'billing_vatid' || // $key == 'billing_firstname' || // $key == 'billing_lastname' || // $key == 'billing_street' || // $key == 'billing_zipcode' || // $key == 'billing_city' || // $key == 'billing_country' || // $key == 'shipping_company' || // $key == 'shipping_firstname' || // $key == 'shipping_lastname' || // $key == 'shipping_street' || // $key == 'shipping_zipcode' || // $key == 'shipping_city' || // $key == 'shipping_department' || // $key == 'shipping_gender' || // $key == 'shipping_country' // ) { // if(!is_string($value) && !is_int($value) && !is_null($value)) { // $value = $this->$key ? $this->$key : 0; // throw new WireException("Address Object only accepts string (string) values"); // } // } return parent::set($key, $value); } public function get($key) { // bd('address get: ' . $key); return parent::get($key); } }
  17. I have a field 'history' to track some field's changes. When changing, for example, the field 'state' in the PW backend I get correct result (1 entry). But when I set 'state' from a template file with: $page->of(false); $page->state = 1138; // field state is Page reference and 1138 is a state with title New $page->save('state'); $page->of(true); … I have two entries in the 'history' field: 2020-02-06 16:19:40 State -/- => New 2020-02-06 16:19:40 State -/- => -/- $this->addHookAfter('Page(template=testtemplate)::changed()', function($event) { /* @var $event HookEvent */ /* @var $page Page */ $page = $event->object; $field = $event->arguments(0); // field $old = $event->arguments(1); // old value $new = $event->arguments(2); // new value $track_fields = ['title', 'state', 'items']; if (!in_array($field, $track_fields)) return; $label = fields()->get($field)->getLabel(); bd($old, $label . ' old'); bd($new, $label . ' new'); $old_value = ($old instanceof Page) ? $old->title : '-/-'; $new_value = ($new instanceof Page) ? $new->title : '-/-'; $history = date('Y-m-d H:i:s') . "\t" . $label . ' ' . $old_value . ' => ' . $new_value; // $page->history = $page->history . PHP_EOL . $history; $page->setAndSave('history', $page->history . PHP_EOL . $history); }); Running this in TracyDebugger will result in two entries as well: $page->setAndSave('state', 'new');
  18. I changed my default setcookie() functions to the newly added $input->cookie method as described in https://processwire.com/blog/posts/pw-3.0.141/ Just noticed no cookies are saved when using PW's $input->cookie->set() (in template file). I am using PW 3.0.148, PHP 7.3 and testing with setcookie('test', 'test') works just fine. Tried to add age, path and domain as well, but nothing works. setcookie('defaultsetcookie', 'works'); $config->cookieOptions = [ 'age' => 604800, 'path' => null, 'domain' => null, 'secure' => null, 'httponly' => false, 'fallback' => true ]; $c = $input->cookie->set('pwcookie', 'wontwork'); print_r( $c ); print_r( $_COOKIE ); Output ProcessWire\WireInputDataCookie Object ( [defaultsetcookie] => works [wire] => 89ortkjmq5dsgb7em2h6ljod9v [pwcookie] => wontwork ) Array ( [defaultsetcookie] => works [wire] => 89ortkjmq5dsgb7em2h6ljod9v [pwcookie] => wontwork ) Any idea what is wrong? It is strange setcookie() works but PW methods won't.
  19. When I check if the page has an image attached, I get the error PHP Warning: count(): Parameter must be an array or an object that implements Countable in But this should be the correct way if ( count(page()->images) ) { $heroimage = page()->images->first()->url; } elseif ( pages()->get('/')->images->first()->url ) { $heroimage = pages()->get('/')->images->first()->url; } I found some issues with this on GitHub, but it was fixed. Using PHP 7.3 and PW 148 (same issue before update).
  20. I've got an existing (pro field) textareas field containing two Page Reference fields. Do you know if subfields are supported using field templates? Those won't work $page->render('related', 'textareas/subfield'); $page->render->textareas; // will output both subfields
  21. Thanks for the link. Had not found the source. It seems the 'data-close' button will only listen for clicks if it is defined in 'data-buttons' as well. But all buttons living there will get the same design. Not that good, when Save and Cancel look the same, but it will work for now.
  22. In a custom process module I open a modal window containing a <form>. When I click the submit button, the modal stays open. I can't find a way, other the X from the title bar, to close the modal window. - How can close the modal, when the submit button was hit? - Or, how can I implement the buttonpane with the Save button like the PageTable module? - Or, at least, how can I include my own close button? That's how I open the modal: $field = wire('modules')->get('InputfieldButton'); $field->attr('id+name', 'status_update'); $field->attr('class', 'pw-modal pw-modal-small ui-button ui-widget ui-corner-all head_button_clone ui-state-default'); $field->attr('value', 'Update'); $field->attr('data-href', './status-update/?id=' . $op->id); $form->add($field); That's my save button $submit = $modules->get('InputfieldSubmit'); $submit->attr('data-close', 'close'); $submit->attr('value', 'Save'); $submit->attr('name', 'submit_dashboard_status_action'); $form->add($submit);
  23. This one has a strange outcome. For example … find('template=city, children.children.created<"14 days ago"'); Result: Hamburg Berlin Hannover Wiesbaden find('template=city, children.children.created>"14 days ago"'); Result: Hamburg Bremen find('template=city, children.children.created<"14 days ago", !children.children.created>"14 days ago"'); Result: Hamburg
  24. Hadn't luck with timestamp either. Changed it now to this, and it's working for me. Anyway, thanks for your answer! $remove = wire('pages')->find('template=city, children.children.created>"14 days ago"'); $cities = wire('pages')->find('template=city, children.children.created<"14 days ago"')->removeItems($remove);
  25. I was trying to get pages that have grand children older than 14 days, but not newer than 14 days. $cities = wire('pages')->find('template=city, !children.children.created>"14 days ago"'); $cities = wire('pages')->find('template=city, children.children.created<"14 days ago"')->not('template=city, children.children.created>"14 days ago"'); $cities = wire('pages')->find('template=city, children.children.created<"14 days ago"')->remove('template=city, children.children.created>"14 days ago"'); The first one is, I guess, not supported by PW (not to mention something like created!>time), but the last two should work in my option. The filter() doesn't work either here. Please note, that all city pages have grand children older than 14 days, so I can't just find('template=cities, children.children.created<"14 days ago"') because that includes those pages having grand children from yesterday for example.
  • Create New...