Jump to content

psy

Members
  • Posts

    636
  • Joined

  • Last visited

  • Days Won

    8

Everything posted by psy

  1. Rebuilt my own site recently using all the knowledge, tips & tricks I've learnt from the PW docs, forums etc, including adding PWA features. Ran it through several publicly available audits and it passed OK - w3c validation, google page speed insights, google lighthouse, etc. Also engaged a digital marketing agency to audit it from a Google search POV. Still some tweaking to do on content & backlink fronts. Overall though happy with the result which could never have been achieved without the help and support of the ProcessWire community. Thank each and everyone of you. https://www.clipmagic.com.au
  2. @Eunico Cornelius Just a thought... on your template have you checked Disable automatic prepend of file: _init.php and/or Disable automatic prepend of file: _main.php?
  3. Try: <?php if ($page->id == 1 ) : ?> <div>your content</div> <?php else: ?> xxx <?php endif; ?>
  4. Welcome to PW and congrats on a lovely site!
  5. @Matze I've used this handy module: to generate content for fields. It's intentionally not automatic, allowing you to specify what/how much dummy content per field. You could maybe make it so with a hook to look for empty CK-Editor textareas on page load?
  6. Haha, me either but it does
  7. Hi @dragan Good questions! Firstly, the video and PWABuilder share the same topic but are otherwise not related. What the video gave me was a simpler approach to adding PWA features to a website, the emphasis being on 'progressive'. A Google search then lead me to PWABuilder. You don't have to do everything at once and while SPA's are PWA's, the reverse is not always true, ie a PWA does not have to be a Vue.js or similar application with REST API's, authentication, etc. Vue.js and its ilk give many more options - JWT, offline DB Storage, push notifications, etc. I needed to get my head back into the basics. The MS PWABuilder is purely a starting point. Many of the niceties you're looking for aren't included, eg a push notification saying "do you want to add it to your homescreen?" I got PWBuilder working for me by putting the following in my site root directory: manifest.json pwabuilder-sw.js pwabuilder-sw-register.js offline.html I then referenced manifest.json, pwabuilder-sw.js and pwabuilder-sw-register.js in my "_main.php" template so every page would get them. Also, see my tips above about what/where to put the generated files. To test that the pwabuilder-sw.js was working, I 'drag-n-dropped' the URL from my browser to the desktop, turned off all internet connectivity then launched the URL from the desktop. All 'while-online-pages' I'd referenced were available offline (also I few I hadn't visited). Other pages I hadn't viewed and hadn't had time to cache before I left the online version, displayed my offline.html page. PWABuilder stores pages offline in the browser cache. Clear the browser cache, lose the offline stuff. What PWABuilder gave me, in combination with ProCache, was super fast load times and pages that could be viewed offline. It's a good starting point, not the be-all-and-end-all. I'm still learning this stuff too
  8. @thomasaull Works great! You say tomato and I say tomato One thing about putting the classes in templates rather than a module is that they can be modified to suit. I tweaked the new ApiHelper to make it more ProcessWire-ish for my own benefit - still does the same thing as your version. public static function checkAndSanitizeRequiredParameters($data, $params) { $sanitizer = wire('sanitizer'); foreach ($params as $param) { // Split param: Format is name|sanitizer method $name = explode('|', $param)[0]; // Check if Param exists if (!isset($data->$name)) throw new WireException(_("Required parameter: '$param' missing!"), 400); // Sanitize Data $parms = explode('|', $param); $sanMethod = 'text'; if (isset($parms[1])) $sanMethod = $parms[1]; if(!method_exists($sanitizer, $sanMethod)) throw new WireException(_("Sanitizer: '$sanMethod' is invalid for param '$name'"), 400); $data->$name = $sanitizer->$sanMethod($data->$name); } return $data; } Thanks for the update.
  9. Thanks for sharing @webhoes Glad it's working for you. Schema's are confusing and you can always write your own and add them to the schema dir of the module (and share here of course!) One thing you may want to check... you're outputting several schemas within one <script> tag... maybe you need to enclose them in brackets, eg: <script>[ .... your output schemas .... ]<script> to show multiple json arrays within one script tag. No expert here and would appreciate comments/recommendations from others. Cheers psy
  10. @webhoes What schema are you using? Please post a copy of your code.
  11. Tips for anyone using PWABuilder: If you upload the manifest.json and js files to the root directory, change all relative urls in the pwabuilder js files to absolute https://yourdomain.com/ urls otherwise the files won't be found in pages lower down the page tree Ditto for the image file URLS in manifest.json, or at least './site/wheveryouhaveyouricons' Minimise the js and manifest.json files so Google won't penalise the site in page speed insights If you don't want to use an index.html file for offline remove references to it from the pwabuilder js files otherwise the service worker registration may fail The pwabuilder js & json files could probably be put in your templates dir providing all scripts & meta links pointed to them correctly. Haven't tried that yet
  12. @dragan The tool gives you some choices about what you want to store offline and if you want an offline.html for content that's not saved locally. Worked for me on mac. Dragged the URL to the desktop, turned off all internet connections, opened the link** with Chrome and Firefox. All worked and any pages I hadn't visited online displayed my offline.html message. ** icon showed Safari even though it's not my default browser, not my PWA icon - an Apple thing? Also, link did not work when opened with Safari which gets back to Apple's lack of support for service workers I guess.
  13. Yep, well took a bit longer reading the doco, experimenting etc and my site was already live. Now I know how to do it, will only take 15 minutes next time. Steps: Create your icons. I only had up to 256x256px. That's old hat. Now you need up to 1024x1024px. Decided to go with my existing website/app icon set anyway. Go to http://www.manifoldjs.com/generator and fill in the blanks Generate the files, download the kit, edit the files and/or your PW template(s) required and upload to the root directory, not /site/ directory, of your ProcessWire site Woohoo!!! Works great with a couple of provisos: The online builder does not work for Mac, iOS and Windows 10 devices, only everything else. Found it somewhat ironic it lacks Windows 10 support as this is a Microsoft product. No surprises there! For Mac, iOS and Win10 you have to use the PWABuilder CLI, almost formerly ManifoldJS CLI as it's going through a name change. Would be ever so grateful to anyone who can tell me how to do that. Followed the instructions to the letter, and also multiple variations, and could not get the CLI version to install/work and I definitely have the latest versions of Node and npm. PWABuilder delivers a manifest.json file and a couple of basic service workers, without all the fuss associated with SPAs, REST APIs etc, for small, informational websites. Watched a video recently that amongst other things, stressed PWA != SPA. Took me a while to get that. (Tip: skip the ads) While not yet perfect, PWABuilder was a good introduction for me to PWAs for ProcessWire.
  14. Yay!!! Got it working successfully with a few tweaks to @thomasaull's templates. In Auth.php: public static function login($data) { // ApiHelper::checkRequiredParameters($data, ['username', 'password']); // $data->username = wire('sanitizer')->selectorValue($data->username); // $data->password = wire('sanitizer')->string($data->password); // All the below work as expected including logging an incorrect Sanitizer method // $data = ApiHelper::checkAndSanitizeRequiredParameters($data, ['username', 'password']); // $data = ApiHelper::checkAndSanitizeRequiredParameters($data, ['username|selectorValuexxx', 'password|string']); $data = ApiHelper::checkAndSanitizeRequiredParameters($data, ['username|selectorValue', 'password|string']); $user = wire('users')->get($data->username); ... The changes to ApiHelper::checkAndSanitizeRequiredParameters($data, $params) were a bit more intense: public static function checkAndSanitizeRequiredParameters($data, $params) { foreach ($params as $param) { // Split param: Format is name|sanitizer $name = explode('|', $param)[0]; // Check if Param exists if (!isset($data->$name)) throw new \Exception('Required parameter "' . $param .'" missing!', 400); $sanitizer = stripos($param,'|') !== false ? explode('|', $param)[1] : 'text'; // Check the sanitizer type is valid (Array copied from Sanitizer method testAll) $sanitizers = array( 'alpha', 'alphanumeric', 'array', 'bool', 'date', 'digits', 'email', 'emailHeader', 'entities', 'entities1', 'entitiesMarkdown', 'fieldName', 'filename', 'float', 'int', 'intArray', 'intSigned', 'intUnsigned', 'markupToLine', 'markupToText', 'minArray', 'name', 'names', 'pageName', 'pageNameTranslate', 'pageNameUTF8', 'pagePathName', 'pagePathNameUTF8', 'path', 'purify', 'removeNewlines', 'selectorField', 'selectorValue', 'string', 'templateName', 'text', 'textarea', 'unentities', 'url', 'varName', ); if (!in_array($sanitizer, $sanitizers)) throw new WireException(_("Invalid sanitizer type: $sanitizer for param $name")); $data->$name = wire('sanitizer')->$sanitizer($data->$name); } return $data; }
  15. Hi @thomasaull In answer to your questions: - Vue Router - thanks for the tip. Hadn't got that far yet - Have run the installed-by-profile Vue Login example countless times - that's where I'm stuck. On the times I do get logged in, I'm only ever logged in as 'guest' - OK I think about $authActive - but in the destructions you ask the dev to to change $authActive to false - Yep, figured that but then in ApiHelper.php, $sanitizer is null so everything falls in a heap - OK - Ahhh yes, the line is just username, password - not username|text, password|text Will try tomorrow. It's late here. Thanks for the help and safe travels Cheers, psy
  16. Hi @thomasaull keen to get it resolved but not urgent in the next few hours. When you get it right is best Just grateful for the API and want to get it working. Have lots of applications for a fully functional PW REST API that handles logins and sanitizer. Happy to help you quality control/troubleshoot. Maybe we can take this conversation offline until the profile is ready? Keep me posted. Thx
  17. Still moving along slowly Auth.php line 37 changed: public static function login($data) { // ApiHelper::checkRequiredParameters($data, ['username', 'password']); ApiHelper::checkAndSanitizeRequiredParameters($data, ['username', 'password']); Next... in ApiHelper.php - again Tracy Debugger not installed/included in default profile: // Sanitize Data if (!$sanitizer) { // \TD::fireLog('WARNING: No Sanitizer specified for: ' . $name . ' Applying default sanitizer: text'); $data->$name = wire('sanitizer')->text($data->$name); } That then forced the next bit in ApiHelper.php to fail too, ie: $data->$name = wire('sanitizer')->$sanitizer($data->$name); as $sanitizer is empty. Maybe not me after all. @thomasaull suspect you have the client file versions out of synch in the profile on github... what with TD calls and incorrect function names, etc. Please confirm.
  18. Got a bit further... this time the error reporting in Router.php pointed to Tracy Debugger which is not included in the profile: public static function handle($class, $method, $vars) { // $authActive = true; $authActive = false; // if(!$authActive) \TD::fireLog('WARNING: Auth disabled!'); Another thing I did not know how to fix was that the Vue build files only worked when uploaded to the same domain as PW. When I uploaded the final build static folder and index.html to another domain, it failed with: Does this mean I can only have one Vue SPA per PW instance? Would be good to have the ability for one PW instance to serve multiple Vue sites. What's your recommendation for configuring, eg install PW in a subfolder and have the Vue build files in the root? TIA psy
  19. @thomasaull Thanks for the profile. Can see you've put a lot of time and effort into it. Have been reading up on PWA's and while Vue.js seems to be the flavour of the month, I really don't like its '/#/' in the URL. Seems Stencil.js is a very similar option and gets around the URL issue. I'm new at this and decided to try your Vue.js option first. Got through most of it thanks to your docs and then got stumped big time at the login process. All good to here using postman: From then on, I got completely lost: Did all that then used postman to try to get the JWT-token and log in. Nope... every response was "user is not logged in" After many & varied attempts, I finally realised that the first conditional in /site/templates/api/Auth.php says if the user isn't log in, throw a WireException... OK but I'm not logged in. I'm trying to log in... Commented out the WireException then my postman GET request gave me my JWT token. Tried to login from my site but still no access??? Doesn't seem to matter whether I have $authActive set to true or false. What am I doing wrong? At what point, if ever, does $authActive get set back to true? Any and all help, especially if they involve more detailed help docs (examples are great!!!!), much appreciated. Thanks psy
  20. Thanks @szabesz clear as mud I'm based in Oz and working on a site that will have a UK clientele as well as Aussies, and possibly EU clients as well. The site needs to collect lots of personal & medical info and want to get this GDPR stuff right from the word go.
  21. How can GDPR not be mandatory yet still have the right to impose huge fines for non-compliance? Interested to know how this impacts storing user profile information in the PW db and/or front-end user form data saved to the DB (eg FormBuilder entry and to-page options). Your thoughts?
  22. Major head spin right now. Downloaded & installed Stencil, read up on Vue.js and downloaded @thomasaull's REST API profile and read Google's PWA stuff all because a simple site I wrote is getting crazy scores on Google's page speed insights yet client loves how fast the site loads on mobile
  23. Little bit chuffed with this new function. You can adapt it to create thumbnail images of external web pages. In my case, it creates a thumbnail image of the publicly viewable Eventbrite event page and attaches it to the PW event page. The $ebResponse is the json_decoded data returned from the webhook call to Eventbrite. /** * Calls the pagepeeker.com API to generate a thumbnail of the Eventbrite public page * @param $ebResponse- the json decoded response from Eventbrite * @param $options = refer pagepeeker API doc - * $options['entrypoint'] - Free 'free'. That makes it: http://free.pagepeeker.com/ * Unbranded 'api'. That makes it: http://api.pagepeeker.com/ * All paid accounts 'api'. That makes it: http://api.pagepeeker.com/ * * $options['size'] - The size of the thumbnail. Available sizes: * 't' Tiny, 90 x 68 pixels * 's' Small, 120 x 90 pixels * 'm' Medium, 200 x 150 pixels * 'l' Large, 400 x 300 pixels * 'x' Extra large, 480 x 360 pixels * * $options['code'] - Your API key. This is optional and recommended to use only for server side calls. * Client side usage does not require it, as we automatically show the thumbnails only * for the domains added in your account. * For the free branded accounts, this parameter is ignored, as we provide the free branded * service for anybody, free of charge. * * Warning * Never use this code on client side pages. We use it for counting your API calls, so having * it used by third parties will count against your monthly quota. * $option['template'] - your PW page template * $option ['field'] - your PW page template image field * $option['page'] - the page to retrieve and attach the image to * * @return mixed * @throws WireException */ public function ___pagePeeker ($ebResponse, $options) { $entrypoints = array('free', 'api'); $options['entrypoint'] = in_array($options['entrypoint'], $entrypoints) ? $options['entrypoint'] : 'free'; $options['size'] = !empty($options['size']) ? $options['size'] : 'l'; $p = $this->wire('pages')->get($options['page']->id); if (!$p->id) throw new WireException($this->className() . _(' invalid page supplied in pagePeeker options')); $templateName = $options['template']; $tpl = $this->wire('templates')->get("name=$templateName"); $imagesField = $options['field']; if (!$tpl->hasField($imagesField)) throw new WireException($this->className() . _(' the template you supplied does not have the image field as specified in pagePeeker options')); $ebLiveUrl = urlencode(str_ireplace("https://www.", "", $ebResponse['url'])); $http = $this->wire(new WireHttp()); // http://{entrypoint}.pagepeeker.com/v2/thumbs.php?size=m&refresh=1&url=wikipedia.org $peekerUrlMake = 'http://' . $options['entrypoint'] . '.pagepeeker.com/v2/thumbs.php?size=' . $options['size'] . '&url=' . $ebLiveUrl; // Get the contents of a URL $response = $http->get($peekerUrlMake); if($response !== false) { $responseObj = json_decode($response); if ($response['error'] == 1) { // error generating thumbnail throw new WireException($this->className() . _(' problem generating pagepeeker thumbnail')); } // OK no errors but thumbnail not ready. Try every pagepeeker server $response = $http->get('http://' . $options['entrypoint'] . '.pagepeeker.com/v2/thumbs_ready.php?size=' . $options['size'] . '&url=' . $ebLiveUrl); $response1 = $http->get('http://' . $options['entrypoint'] . '1.pagepeeker.com/v2/thumbs_ready.php?size=' . $options['size'] . '&url=' . $ebLiveUrl); $response2 = $http->get('http://' . $options['entrypoint'] . '2.pagepeeker.com/v2/thumbs_ready.php?size=' . $options['size'] . '&url=' . $ebLiveUrl); $response3 = $http->get('http://' . $options['entrypoint'] . '3.pagepeeker.com/v2/thumbs_ready.php?size=' . $options['size'] . '&url=' . $ebLiveUrl); $response4 = $http->get('http://' . $options['entrypoint'] . '4.pagepeeker.com/v2/thumbs_ready.php?size=' . $options['size'] . '&url=' . $ebLiveUrl); /** * Finally, thumbnail is ready * Download the image: http://{entrypoint}.pagepeeker.com/v2/thumbs.php?size=m&url=wikipedia.org * Check all the available pagepeeker servers to speed up the download **/ if ($response) { $fromUrl = "http://" . $options['entrypoint'] . ".pagepeeker.com/v2/thumbs.php?size=" . $options['size'] . "&url=" . $ebLiveUrl; } elseif ($response1) { $fromUrl = "http://" . $options['entrypoint'] . "1.pagepeeker.com/v2/thumbs.php?size=" . $options['size'] . "&url=" . $ebLiveUrl; } elseif ($response2) { $fromUrl = "http://" . $options['entrypoint'] . "2.pagepeeker.com/v2/thumbs.php?size=" . $options['size'] . "&url=" . $ebLiveUrl; } elseif ($response3) { $fromUrl = "http://" . $options['entrypoint'] . "3.pagepeeker.com/v2/thumbs.php?size=" . $options['size'] . "&url=" . $ebLiveUrl; } elseif ($response4) { $fromUrl = "http://" . $options['entrypoint'] . "4.pagepeeker.com/v2/thumbs.php?size=" . $options['size'] . "&url=" . $ebLiveUrl; } else { throw new WireException('Did not get a response from PagePeeker'); } $imgName = "eb-preview-" . $ebResponse['id']; $toFile = $this->wire('config')->paths->assets . "files/" .$p->id .'/'. $imgName . '.jpg'; $p->of(false); $img = $http->download( $fromUrl, $toFile); // OK we have the downloaded file, now add it to the page database info for the images field $imgUrl = $this->wire('config')->urls->assets . "files/" .$p->id .'/'. $imgName . '.jpg'; $pwImage = new Pageimage($p->$imagesField, $toFile); $pwImage->description = $ebResponse['name']['text']; $pwImage->tags = "eb-preview"; $p->$imagesField->add($pwImage, $imgUrl); return $img; } else { throw new WireException("HTTP request failed: " . $http->getError()); } }
  24. Developing this module has definitely been a trial by fire. Getting there though and for sure, reading the PW API docs helped and not just what I thought I needed to know but other stuff as well. Was so focussed on: $eb = $modules->get('EventbriteAPIv3')->login(); in my webhook template which failed every time, I completely overlooked: $eb = wire('modules')->getModule('EventbriteAPIv3', array('noPermissionCheck' => true))->login(); Of course the webhook template/response is not a logged-in admin with permission to change stuff... Doh!
  25. Channelling Thomas Edison again. Problem I've having now is not Eventbrite but PW. The module is configured to not autoload although I've tried that too. I have 2 page templates: 1. Calls my EventbriteAPIv3 module that returns data to a 'normal', viewable page template. All good there 2. Calls my EventbriteAPIv3 in the EB web hook endpoint page template. Not matter how I try to configure it, the module is never loaded. Instead I get any number of PW error messages, eg: When I use $eb = $modules->get(EventbriteAPIv3)->login() or $eb = wire('modules')->get('EventbriteAPIv3')->login() in the page template: Error: Exception: Unknown Selector operator: '' -- was your selector value properly escaped? (in /home/xxxx/xxxx.com/wire/core/Selectors.php line 378) Other error message include, depending on the method I chose to load it: Error: Uncaught Error: Call to a member function getAccessCode() on null in /home/xxxxxx/xxxxxx.com/site/templates/eventbrite-webhook.php:21 Have even tried putting the $modules->get call it in _init.php without success. Reading the PW doco, google searching and running out of ways to vary the call yielded nothing. All suggestions, help & guidance most welcome.
×
×
  • Create New...