Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


eelkenet last won the day on December 5 2018

eelkenet had the most liked content!

Community Reputation

64 Excellent

About eelkenet

  • Rank
    Full Member

Profile Information

  • Gender
    Not Telling
  • Location

Recent Profile Visitors

2,045 profile views
  1. I'm sorry @thomasaull, but I don't believe I understand the module's inner workings well enough to pull that off Here is the final cleaned-up and more secure 'api' template that I am using in between the RestApi router and ProCache, perhaps it can be of some help: <?php // Pre-check for unwanted symbols (hint from Ryan) if (strpos($input->urlSegmentStr(), '.') !== false) { throw new Wire404Exception(); } // Build request URL $protocol = $input->scheme() . "://"; $endpoint = $modules->get("RestApi")->endpoint; $hostname = $config->httpHost; $url = $protocol.$hostname."/".$endpoint."/".$input->urlSegmentStr(); // This bit slows the traffic down a bit, but seems more secure $http = new WireHttp(); $status = $http->status($url); if ($status === 200) { return $http->get($url); } // Prevent the creation of empty caches: throw new Wire404Exception();
  2. Hi @thomas, no problem. And yes, definitely! I think that would be much better. Anything that comes from inside the regular page rendering can be cached with ProCache.
  3. eelkenet


    Hi @Wanze, congrats on your nice module! I'm currently testing it out for a client and find it overall very nice, thank you for your work! I have some feedback, even though I'm not sure if I'm understanding everything you do correctly. So please excuse me if I'm mistaken Having to set the default values for the meta tags on the field/template level, instead of using the PageTree (the Page level) seems unpractical. Most of the time I give a site editor access to the PageTree, sometimes to some modules, but I definitely keep them away from 'dangerous' stuff like Fields and Templates. However, editors should always be able to edit the SEO information without bugging the developer for an update. In other words, the preferred place for the default SEO information should imho be at the root of the tree: the homepage. (Or perhaps inside the a module config). To me it would make total sense that SEO information follows the same inheritance structure as pages do. Often rendered titles will consist of a page title and some ancestor title. So you should be able to select the parent's title and expand on it, much like the 'List of fields to display in the admin Page List') -home (title: "My Site") |-projects (title: "Projects") ||-project1 (title: "Project number 1") ||-project2 (title: "Another project") It would make sense to be able to get the following: -home (seo.meta.title: {title} would result in "My Site") |-projects (seo.meta.title: {title} - {parent.title} would result in "Projects - My Site") ||-project1 (seo.meta.title: {title} - {parent.parent.title} would result in "Project number 1 - My Site") ||-project2 (seo.meta.title: {title} | {parent.title} | {parent.parent.title} would result in "Another project | Projects | My Site")
  4. Ah, I did not know that. Makes sense as a limit for the full posts. For titles though.. not sure. Besides, Invision Community (the forum software) supports it on their own support forum just fine: https://invisioncommunity.com/search/?q=SEO
  5. While I know there are a couple of modules, topics and posts regarding SEO, it is impossible to search for these: for instance https://processwire.com/talk/search/?q=SEO&amp;type=forums_topic yields no results. It seems that the minimum input length is currently set at 4 characters, though this is not mentioned. So my request, if technically feasible: can the minimum search length please be reduced to 3 character long strings? If possible 2-letter combinations could be valuable as well, though that could be a bit too much of a strain on the database I guess.
  6. Congratulations on the launch, Ryan! I do have issues with the iMac/screenshots images though, as others have said before me. Not because it is an iMac, but because of the impossible size of the content. My first reaction as a visitor is to squint my eyes and to move my head close to the monitor to see the actual PW screenshots inside it. And to be honest I think that is a problem, because: The very first impression, the first thing people look at, on any website will always be graphics/images, not text. You only get one shot at a first impression The first impression should be very clear and very convincing The iMac frame and code in the background take about 75% of the available real estate, making the actual screenshots tiny! A simple sliding carousel or slideshow would suffice, possibly showing steps like: The pagetree Editing a page Cropping an image Creating fields Creating template
  7. Great work Ryan, thank you! I fully agree with this. Our main use of Processwire is as a headless CMS / CMF for Single Page Applications. As a possible future user I would be very interested in learning about how PW can be used in this way. I would look for that on the 'Output' page (https://processwire.com/newsite/docs/front-end/output/). A simple JSON API example, without the use of any external modules, would suffice here I think.
  8. I had a quite some trouble getting this to work with the content from a ProFields Table, as this does not work the same as with a Repeater or PageTable. But I am happy to say that treating those fields as a 'file' works, by setting this in the options array. Ie: <?php $finder = new RockFinder("template=template_name,limit=10", ["title", "some_field_name"]); $field = $finder->addField("my_table_field", ["column_name", "other_column"], ["type" => "file"]); $field->seperator = ", ";
  9. Hmm, that is weird, in that case it is probably being reset somewhere. Have you tried doing a full search of your project's code for places where it might be overridden? Maybe some module or template is accidentally setting it, instead of checking for the value.
  10. You should not overwrite this file. Instead, edit the config in site/config.php.
  11. I ran into this issue too. I edited the Mollie module to fit my own needs, a bit too many changes to create a merge request, but it deals with this issue. <?php namespace ProcessWire; // Here you can find more information about the Mollie php api https://github.com/mollie/mollie-api-php require_once __DIR__ . "/vendor/autoload.php"; class PaymentMollie extends PaymentModule { public static function getModuleInfo() { return [ 'title' => 'PaymentMollie', 'version' => '0.0.2', 'summary' => 'Mollie Payment method', 'singular' => false, 'autoload' => false, 'requires' => 'ProcessWire>=3.0.98, PaymentModule', ]; } public function init() { ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); } public function getTitle() { return $this->_("Mollie: iDeal, Bancontact"); } public function getFailureReason() { return "Error"; } public function processPayment() { $payment_id = wire()->input->post->id; $order_id = wire()->input->urlSegment2; $mollie = new \Mollie\Api\MollieApiClient(); $mollie->setApiKey($this->test_api_key); if ($this->live_check == "1") { $mollie->setApiKey($this->api_key); } $payment = $mollie->payments->get($payment_id); $order_id = $payment->metadata->order_id; wire()->log->save("mollie", "Processing payment for... $order_id"); if ($payment->isPaid() == true) { wire()->log->save("mollie", "Order $order_id was paid using mollie!"); $order = wire()->pages->get($order_id); $order->of(false); $order->pad_paid = time(); $order->addNote($this->_("Order paid using Mollie") . ": " . $payment->id); $order->removeStatus(Page::statusUnpublished); $order->save(); return true; } elseif ($payment->isOpen() == FALSE) { return false; } return false; } public function getMollieMethods() { $mollie = new \Mollie\Api\MollieApiClient(); $mollie->setApiKey($this->test_api_key); if ($this->live_check == "1") { $mollie->setApiKey($this->api_key); } $methods = $mollie->methods->all(); $return = [ ]; foreach ($methods as $method) { $return[] = [ "title" => htmlspecialchars($method->description), "icon" => htmlspecialchars($method->image->size1x), "icon2x" => htmlspecialchars($method->image->size2x), ]; } return $return; } public function render() { $output = ""; $mollie = new \Mollie\Api\MollieApiClient(); $mollie->setApiKey($this->test_api_key); if ($this->live_check == "1") { $mollie->setApiKey($this->api_key); } $paymentInfo = [ "amount" => [ "value" => number_format(($this->getTotalAmount() /100), 2, '.', ''), "currency" => 'EUR', ], "description" => "Bestelling van: " . $this->customer->givenName . " " . $this->customer->familyName, "redirectUrl" => $this->httphost . "checkout/?id=" . $this->id, "webhookUrl" => $this->httphost. "checkout/processmollie/" . $this->id . "/", // Specify here wat you want "metadata" => [ "order_id" => $this->id, /* "customer_name" => $this->customer->givenName, "customer_familyName" => $this->customer->familyName, "customer_address" => $this->customer->streetAddress, "customer_locality" => $this->customer->locality, "customer_postalCode" => $this->customer->postalCode, "customer_country" => $this->customer->country, "customer_email" => $this->customer->email */ ], ]; // $output .= "<pre>" . print_r($paymentInfo, true) . "</pre>"; $payment = $mollie->payments->create($paymentInfo); wire()->log->save("mollie", "Creating the payment... $order_id"); // Type here your custom HTML // use $payment->getPaymentUrl() as url for your payment link foreach ($methods as $method) { $output .= '<div style="line-height:40px; vertical-align:top">'; $output .= '<img src="' . htmlspecialchars($method->image->size1x) . '" srcset="' . htmlspecialchars($method->image->size2x) . ' 2x"> '; $output .= htmlspecialchars($method->description) . ' (' . htmlspecialchars($method->id) . ')'; $output .= '</div>'; } $output .= "</div>"; $output .= "<div><form action='{$payment->getCheckoutUrl()}'> <button type='submit'>". __('Pay') ."</button></form></div>"; return $output; } public static function getModuleConfigInputfields(array $data) { $inputfields = new InputfieldWrapper(); // Test API $live_api_field = wire('modules')->get('InputfieldText'); $live_api_field->name = 'test_api_key'; $live_api_field->label = __("Test API Key"); $live_api_field->notes = __(""); if (isset($data['test_api_key'])) { $live_api_field->value = $data['test_api_key']; } $inputfields->add($live_api_field); // Live API $test_api_field = wire('modules')->get('InputfieldText'); $test_api_field->name = 'api_key'; $test_api_field->label = __("Live API Key"); $test_api_field->notes = __(""); if (isset($data['api_key'])) { $test_api_field->value = $data['api_key']; } $inputfields->add($test_api_field); // Select live or test API $check_api_field = wire('modules')->get('InputfieldCheckbox'); $check_api_field->name = 'live_check'; $check_api_field->checked = $data['live_check']; $check_api_field->label = __("Use Live API Key"); $check_api_field->notes = __("If not selected, the test-api will be used. Keep in mind that you also have to activate the Live api on your Mollie dashboard"); if (isset($data['live_check'])) { $check_api_field->value = $data['live_check']; } $inputfields->add($check_api_field); // HTTP Host url $httphost_field = wire('modules')->get('InputfieldURL'); $httphost_field->name = 'httphost'; $httphost_field->label = __("HTTP Host"); $httphost_field->notes = __(""); if (isset($data['httphost'])) { $httphost_field->value = $data['httphost']; } $inputfields->add($httphost_field); return $inputfields; } }
  12. I ran into an issue that is related to the way the RestAPI circumvents the pagetree structure (running the checkIfApiRequest hook before rendering any page). This method made it impossible to use ProCache for API requests that could (and should) return a cached result, such as for static site content. I thought about creating a custom caching system on top of RestApi, but ProCache is just too well designed to ignore here. I wrote a post about this on the ProCache VIP-forum, but as this forum is not accessible to all people I'd like to share my (admittedly hacky) solution for this. Basically I add another (cacheable) endpoint in the pagetree, which pipes the request to the RestApi endpoint: Create a new template and corresponding page (I called both 'api'). Set the content-type of this template to application/json, and disable any prepending/appending of files. Add the following code to the template: <?php //site/templates/api.php $protocol = $config->https ? "https://" : "http://"; $endpoint = $modules->get("RestApi")->endpoint; $hostname = $config->httpHost; $segments = implode("/", $input->urlSegments); $url = $protocol.$hostname."/".$endpoint.$segments; return file_get_contents($url); I'm sure there would be a better, cleaner way of doing this. A current downside is that there now are 2 seemingly identical endpoints for my site. One is cached, and the other is 'live'. Any ideas?
  13. Great, that works! Thank you for the fix.
  14. I installed the module (v0.1.3) on an existing site, running PW in the current Master release, v3.0.98 on Php 7.2. After enabling the module for a regular Fieldset (Open) I kept running into this error: Method InputfieldFieldsetOpen::wrapClass does not exist or is not callable in this context This is because Inputfield::wrapClass() has not been added to the Master yet, it is only available on the ProcessWire dev release (currently 3.0.119). The fix for this issue is to replace lines 107-109 with: // Add classes to inputfield $inputfield->wrapClass .= ' MinimalFieldset'; if(!$field->no_spacing) $inputfield->wrapClass .= ' MinimalFieldsetSpaced';
  • Create New...