Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/20/2022 in all areas

  1. Hi @Nomak I think you don't need to use these library to access the shopify api. Take a look at the following link: https://gist.github.com/calufa/c575b31291bb000fbf59 Gideon
    2 points
  2. Coming to an IntelliJ IDE (like PHPStorm) near you soon. Live Templates or snippets provide a short way to write repeating code. You enter an abbrevitation and the editor completes the code for you. Here is one example when I want to setup a new module: phpstorm64_aT7Nj2gxSv.mp4 @bernhard Has snippets for VSCode in his great RockMigrations module also, be sure to check them out, if you use VSCode. As I use RockMigrations in every PW installation I also add snippets for migrations: phpstorm64_fAD9MoUJLE.mp4
    1 point
  3. Hi @Nomak. Welcome to the forums. Is this a one-off? If yes, another option is to export the products (in the Products Dashboard in Shopify admin) as CSV and then use that to import the products into ProcessWire. At that point you can use the ProcessWire API + PHP to do the imports or modify the CSV and use a module such as ImportPagesCSV to import to ProcessWire.
    1 point
  4. @bernhard This is the function in the module file: <?php /** * Get changed watchfiles * @return array */ public function getChangedFiles() { $changed = []; foreach ($this->watchlist as $file) { // remove the hash from file path // hashes are needed for multiple callbacks living on the same file $path = explode(":", $file->path)[0]; $m = filemtime($path); /////////// LINE 1282 if ($m > $this->lastrun) { $changed[] = $file->path; $file->changed = true; } } return $changed; } It's this Line: $path = explode(":", $file->path)[0]; Explode the Path -> it's just C (should be "'C:/apache2/htdocs/site/migrate.php'") When i remove the explode the "C" Error is gone, but the repeater error remains.
    1 point
  5. I have a problem with the latest version. When I use the shortcuts with external links, I always get the following error: I think the check doesn't fit that way (line 226): if (!$page || !$page->url) { Because if "$page" does not exist, then "$page->url" will cause an error. Also added an issue on github ?https://github.com/daun/processwire-dashboard/issues/41 /edit: the new version 1.5.2 fixed this bug ? thanks!
    1 point
  6. Re leaking: I believe nginx uses the request url as the cache key and that only GET requests are cached (not sure about OPTIONS or HEAD). So if you have caching enabled and a logged in user, Wilma, requests /processwire/user to see their profile, the next user, logged in or not, will also see Wilma's record. Typically it's ok to disable caching for logged in users, and/or you can also disable caching on certain urls (or patterns of url) that you know to be sensitive. Don't know if this is helpful or not, but here's the sort of thing I use for Drupal. map $http_cookie $session_cookie_set { default 0; ~SESS 1; # PHP session cookie } ## Identify ajax requests so we can choose to not cache them map $uri $is_drupal_ajax_request { default 0; /system/ajax 1; } # ... then in your server block ... fastcgi_cache_bypass $session_cookie_set $arg_nocache $is_drupal_ajax_request; fastcgi_no_cache $session_cookie_set $arg_nocache $is_drupal_ajax_request; What this does is: set up a variable `$session_cookie_set` which will be 1 if there is a PHP Session cookie in the request Set up a variable `$is_drupal_ajax_request` if the path is `/system/ajax` (a special path for drupal, but you can add your own var name and url patterns in here for your own use/processwire uses). Tells nginx to bypass and not cache results if any of these, or the `nocache` URL query variable is set. I'm keen to use pw with nginx because .htaccess is ineffficient (from what I've read) and because I get on better with the reasoning of nginx's config; it seems to have fewer quirks than apache!
    1 point
  7. Thats a great concept! I have to think about this. You can also use a page reference field in a PAGEGRID block template to store a reference to a PAGEGRID item page. This allows you to render a PAGEGRID item on multiple pages (e.g. useful for headers or footers). If you change the content or styling of the referenced page it will update across your whole site.
    1 point
  8. Hello! First to say, thanks for your great work. I have a mulitlanguage site setup and if I log out as user I have following error message: I can't find a solution for that. Thanks for your help!
    1 point
  9. This last week my wife and daughter took a trip to NYC and it was my daughter's first time there. I was browsing around online looking at things they could do and so I visited the Guggenheim museum website to look into that option... I've always been a fan of the building, a Frank Lloyd Wright masterpiece. In addition to New York, I learned from the website that Guggenheim also has museums in Abu Dhabi, Bilbao and Venice, so I clicked through to view them as well. I really liked the Venice Guggenheim website, which had a much nicer website than the other locations. It was such a nice site that I was curious what they were running, so I viewed the source and... not WordPress (like the others), but ProcessWire. What a nice surprise. Then I was curious about who made such a nice site and there was a credits link in the bottom right corner that says the site was made by basili.co, nice work! It's always fun to come across a ProcessWire powered website randomly like that, and I thought you all would enjoy this one too. This week there are fairly minor updates on the core dev branch. Though the updates include one I've been meaning to do for a long time: improve the API for processing Inputfield forms. Previously there's been no way to check if a form is submitted, short of checking an $input variable yourself. Today I committed an update that adds a $form->isSubmitted() method that solves that, and more. It can identify which form was submitted, which submit button was used, and it also performs additional checks to make sure it's a valid submission before deciding that it's a form worth processing. It improves reliability, accuracy and security. Next week I'll be updating several of the admin forms to use it, among other updates. A few other useful helper methods were added to the Inputfield forms API as well. I realize that these updates may only be of interest to module authors, but I like keep you up-to-date with the week's updates either way. Thanks for reading and have a great weekend!
    1 point
  10. This week on the core dev branch we’ve got some major refactoring in the Page class. Unless I broke anything in the process, it should be more efficient and use less memory than before. But a few of useful new methods for getting page fields were added in the process. (A couple of these were also to answer feature request #453). Dot syntax You may have heard of dot-syntax for getting page fields, such as $pages->get('parent.title') where “parent” can be any field and “title” can be any field that has subfields. This is something that ProcessWire has supported for a long time, but it doesn’t get used much because it was disabled when output formatting was on. So it wasn’t something you could really count on always being there. Now you can — it is enabled all of the time. But it’s also been rewritten to be more powerful. When using dot syntax with a multi-value field (i.e. any kind of WireArray value) you can also specify field_name.first to get just the first value or field_name.last to get just the last value. i.e. $page->get('categories.first'); will take a value that was going to be a PageArray (‘categories’) and return just the first Page from it. Bracket syntax With bracket syntax you can call $page->get('field_name[]') with the (‘[]’ brackets at the end) and it will always return the appropriate array value for the type, whether a PageArray, WireArray, Pagefiles/Pageimages, or regular PHP array, etc. This is useful in cases where you know you’ll want a value you can foreach/iterate. Maybe you’ve got a Page field that set set to contain just 1 page, or maybe you’ve got a File/Image field set to contain just 1 file. But you want some way to treat all of your page or file/image fields the same, just append “[]” to the field name in your $page->get() call and you’ll always get an array-type value, regardless of the field settings. This bracket syntax can also be used for getting 1 value by index number. Let’s say you’ve got a page field named “categories” that contains multiple pages. If you want to get just the first, you can just call $page->get('categories[0]'); If you want to get the second, you can do $page->get('categories[1]'); This works whether the field is set to contain just one value or many values. Using the first index [0] is a good way to ensure you get 1 item when you may not know whether the field is a single-value or multi-value field. Another thing you can do with the bracket syntax is put a selector in it to filter a multi-value field right in the $page->get() call. Let’s say you want all categories that have the word “design” in the name. You can call $page->get('categories[title%=design]'); If you want just the first, then $page->get('categories[title%=design][0]'); What’s useful about using selectors in brackets is that this does a filter at the database-level rather than loading the entire ‘categories’ field in memory and then filtering it. Meaning it's a lot more memory efficient than doing a $page->get('categories')->find('title%=design'); In this way, it’s similar to the already-supported option to use a field name as a method call, for instance ProcessWire supports $page->field_name('selector'); to achieve a similar result. Dot syntax and bracket syntax together You can use all of these features together. Here’s a few examples from the updated $page->get() phpdocs: // get value guaranteed to be iterable (array, WireArray, or derived) $images = $page->get('image[]'); // Pageimages $categories = $page->get('category[]'); // PageArray // get item by position/index, returns 1 item whether field is single or multi value $file = $page->get('files[0]'); // get first file (or null if files is empty) $file = $page->get('files.first'); // same as above $file = $page->get('files.last'); // get last file $file = $page->get('files[1]'); // get 2nd file (or null if there isn't one) // get titles from Page reference field categories in an array $titles = $page->get('categories.title'); // array of titles $title = $page->get('categories[0].title'); // string of just first title // you can also use a selector in [brackets] for a filtered value // example: get categories with titles matching text 'design' $categories = $page->get('categories[title%=design]'); // PageArray $category = $page->get('categories[title%=design][0]'); // Page or null $titles = $page->get('categories[title%=design].title'); // array of strings $title = $page->get('categories[title%=design].title[0]'); // string or null // remember curly brackets? You can use dot syntax in there too… echo $page->get('Page “{title}” has {categories.count} total categories'); I’m not going to bump the version number this week because a lot of code was updated or added and I’d like to test it for another week before bumping the version number (since it triggers the upgrades module to notify people). But if you decide to upgrade now, please let me know how it works for you or if you run into any issues. Thanks for reading, have a great weekend!
    1 point
  11. I work every day with ProcessWire as 90% of our websites are built with it. We have a base install that we use for every new project, if anything from the weekly updates is an improvement on what we use in there, then we update our base install which will have the improvement on our next project. We also have a lot of retained clients who pay monthly to keep things running smoothly, again if there are any improvements in the weekly updates, we can slowly apply these to the retained projects going forward. The last major improvement in our workflow was the combo field which we use on all our latest projects, we wouldn't know about that if the weekly updates didn't exist. You mention being productive which I think is the best thing about ProcessWire. We have installs from years ago that are still running, and we don't have to worry about them, or care how they were built even if the client is not on a retainer, we just leave them. However, the client may come back and request some updates, we can start with running all the upgrades knowing that we have had very few issues in the past with just running upgrades, and we already know that behind the scenes there will be improvements in doing this, and improvements if we wish to use them with our coding. I guess what I am trying to say is you don't need to worry about the weekly updates if they don't have an impact on you, but the next time you check the documents you may see something that you can use as an improvement. I am sure nobody remembers all the improvements, I don't, nobody uses all of them, I don't, but they are there to use if you want and know about them. Everything still works with a site that you have already built if you just run an upgrade. There may be 51 weekly posts in a year I have no interest in, but 1 weekly post which is golden, I will take that for something I don't pay for (other than through the Pro modules). How does it make me learn coding, every day is a school day and seeing how things are done in ProcessWire makes me think in different ways when I am using other tools, I suppose that is what will happen when 90% of our websites are built with ProcessWire.
    1 point
  12. Example with a multidimensional array. RepeaterMatrix fieldname = 'fieldname' first level: page where the repeater field lives in, indexed by ID second level: per page repeater items indexed by ID third level: field inside repeater indexed by name $rp = $pages->find('fieldname.count>0'); $return = []; foreach ($rp as $p) { $return[$p->id] = []; // RepeaterMatrixPageArray foreach ($p->fieldname as $item) { if ($item->type != 'basic') continue; $return[$p->id][$item->id] = []; // RepeaterMatrixPage foreach ($item->template->fields as $repeaterField) { if ($repeaterField == 'repeater_matrix_type') continue; // we do not need this if ($item->$repeaterField === '') continue; // if you want to ignore empty strings $return[$p->id][$item->id]["$repeaterField"] = $item->$repeaterField; } // remove if empty if (empty($return[$p->id][$item->id])) unset($return[$p->id][$item->id]); } // remove if empty if (empty($return[$p->id])) unset($return[$p->id]); } var_dump($return);
    1 point
  13. From the documentation for "Name format for children": So if you want date format "U" you would enter that along with at least one non-alphanumeric character - e.g. "/U" or "U/". Do not enter "date()" anywhere in the format. ProcessSetupPageName is not the same as the core "Name format for children" feature and it has different format requirements.
    1 point
  14. With the diagnostics module(s) there is also one for (missing) server image feature detection.
    1 point
  15. Adding to @Macrura's suggestion: rather than do the preg_replace and str_replace to remove the unwanted doctype, body, etc, you can avoid those by using an options parameter for loadHTML(): $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    1 point
  16. This code can be placed into any generic site utilities module and you can add the hook in the init(); you can for example take the hello world module and clone it, rename to SiteUtilities, and then you can throw all of your custom stuff in there, instead of doing independent modules for everything.. $this->pages->addHookBefore('save', $this, 'addImageDataAttributes'); public function addImageDataAttributes($event) { $page = $event->arguments[0]; $ta_field = 'body'; // change to your editor field that holds the images $img_field = 'images'; // change to the name of the images field if(!$page->$img_field || !$page->$ta_field) return; $html = $page->$ta_field; if (strpos($html,'<img') === false) return; //return early if no images are embedded in html $dom = new \DOMDocument(); $dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); $images = $dom->getElementsByTagName('img'); if(!$images->length) return; // not needed? $imgCount = 0; foreach ($images as $image) { $img_url = $image->getAttribute('src'); $path_parts = pathinfo($img_url); $imgName = $path_parts['basename']; $sysImage = $page->$img_field->get("name={$imgName}"); $width = $sysImage->width; $height = $sysImage->height; $image->setAttribute('data-width', $width); $image->setAttribute('data-height', $height); $imgCount++; } if(!$imgCount) return; $page->of(false); $page->$ta_field = preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $dom->saveHTML())); $page->save($ta_field); $this->message("image links updated with data attributes."); } This has been tested and works, but it will only retain the data attributes if your CK editor settings allow it..
    1 point
  17. i usually use a custom module and put all of my custom admin stuff there, e.g.: public function ready(){ if($this->page->process == "ProcessPageEdit"){ $this->addHookAfter('ProcessPageEdit::buildFormContent', $this, 'mySpecialThing'); } } public function mySpecialThing(HookEvent $event) { $form = $event->return; $field = $this->modules->get("InputfieldMarkup"); $field->markupText = "<h3>My Special Thing</h3>"; $form->prepend($field); } // end function
    1 point
×
×
  • Create New...