Jump to content

eelkenet

Members
  • Posts

    132
  • Joined

  • Last visited

  • Days Won

    4

Posts posted by eelkenet

  1. On 9/7/2023 at 12:25 PM, eelkenet said:

    Hi @Sebi, I'm about to start work on a web-app that will (hopefully) use AppApi with 2-factor authentication, using the TOTP module from Ryan.
    I would like to use the Double JWT authentication for the most secure set-up.

    I have moved away from the Double JWT solution for now, as PHP sessions seem to work fine for my application.
    Also I managed to implement TFA validation, by editing the `classes/Auth.php` file.
    That seemed to be the only way I could do so: I tried hooking into ___doLogin() but couldnt figure out the order of things. See below!

    So, I replaced line 164:

    $loggedIn = $this->wire('session')->login($user->name, $password);

    With

    // Add Tfa authentication through TfaTotp
    if ($user->hasTfa()) {
        $tfa = $user->hasTfa(true);
    
        // Get code from incoming data
        // This only works if credentials + 2FA get sent inside the body
        $code = null;
        if (
            isset($data->tfacode) &&
            !empty('' . $data->tfacode)
        ) {
            $code = $data->tfacode;
        }
    
        $settings = $tfa->getUserSettings($user);
        if ($code && $tfa->isValidUserCode($user, $code, $settings)) {
            $loggedIn = $this->wire('session')->login($user->name, $password);
        } else {
            throw new AuthException("Invalid TFA code",  401);
        }
    } else {
        $loggedIn = $this->wire('session')->login($user->name, $password);
    }

    And then added the 2FA in the body request:

    // inside a log-in method
    
    const credentials = {
      email: this.identification,
      password: this.password,
      tfacode: this.tfacode,
    };
    
    const response = await fetch('/api/auth', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'MY_API_KEY',
      },
      body: JSON.stringify(credentials),
    });
    
    if (response.ok) {
      return response.json();
    } else {
      let error = await response.json();
      throw new Error(JSON.stringify(error));
    }

    I have also managed to do a proof of concept of a register route that works in combination with the TfaTotp module, but that needs some polishing.

     


    Update: I figured out that, in order to get be able to hook into Auth::doLogin, I needed to check the 'Deactivate URL Hook' toggle in the AppApi module settings.
    After doing so, I can now successfully hook and check for the Tfa, hurrah!

    // In ready.php
    
    wire()->addHookAfter('Auth::doLogin', function (HookEvent $event) {
    
      $log = wire('log');
      $session = wire('session');
    
      // Get the original return value of ___doLogin
      $originalReturnValue = $event->return;
    
      // Check if the original login was successful
      if (isset($originalReturnValue['username']) && !empty($originalReturnValue['username'])) {
    
        $username = $originalReturnValue['username'];
        $user = $event->wire('users')->get("name=$username");
    
        // Check if the user has TFA activated
        if ($user->hasTfa()) {
    
          $tfa = $user->hasTfa(true);
    
          // Get code from incoming data
          // This only works if 2FA gets sent inside the body, along with password and username
    
          $data = $event->arguments(0);
          $code = null;
          if (isset($data->tfacode) && !empty('' . $data->tfacode)) {
            $code = $data->tfacode;
          }
    
          $settings = $tfa->getUserSettings($user);
          if ($code && $tfa->isValidUserCode($user, $code, $settings)) {
    
            $log->save("tfaLogin", "Tfa code = correct!");
            $event->return = $originalReturnValue;
          }
    
          // Incorrect Tfa, sign out and throw 401
          else {
    
            $log->save("tfaLogin", "Tfa code = incorrect, do not allow logging in");
            $session->logout();
    
            throw new AuthException("Code incorrect!",  401);
          }
        }
    
        // No Tfa enabled, sign out and throw 401
        else {
    
          $log->save("tfaLogin", "User does not have Tfa enabled.. do not allow logging in!");
          $session->logout();
    
          throw new AuthException("TFA not enabled!",  401);
        }
      }
    });

     

     

  2. Hi @Sebi, I'm about to start work on a web-app that will (hopefully) use AppApi with 2-factor authentication, using the TOTP module from Ryan.
    I would like to use the Double JWT authentication for the most secure set-up.

    As I understand, this would currently not be possible, except maybe if I resort to PHP session instead and create my own login endpoint that implements some of the TfaTotp module methods. Is that correct?

    Or do you have any pointers as to how to implement this with Double JWT?

  3. Any reason for not using PW's own $input variable? https://processwire.com/api/ref/wire-input/

    First of all, your example code should probably be a POST request as you are submitting data and not requesting a page for instance.
    Then you can simply log the received data with something like this, in order to get the content from your object {'daten':'...'}, and validate it as email.

    $email = $input->post("daten", "email");
    if ($email) {
    	//... do what you need to do. For instance create a record, and echo some valid JSON as a status message to display to the user. 
    }

     

  4. Hi @kixe, thank you for this very handy module. I've come up with a situation where I would like access to the $hsl value that lives inside the formatColorString method.
    So I would kindly like to request you add a 10th output: the pure HSL value as an indexed array.

     At the FieldtypeColor::___getConfigInputFields method, you could add

    $f->addOption(10, $this->_('array([0,360], [69.2%], [56.7%]) indexed array: H,S,L'));

    And then the end of the FieldtypeColor::formatColorString method, you could add

    if ($of === 10) {
       return $hsl;
    }

    If you want I can make a pull request for this, but since it's a minor change maybe this way is fine too?
    Thanks again!

  5. Update: I have, in a way, accomplished my goals! I have not been successful at adding any <optgroup>s, BUT I did figure out a way around my issue.
    Instead of adding the unsupported optgroups, I just inject extra, disabled <option>s. These options can get a label, so I can use them as sort of dividers between the rows of pages

    Currently I group them by template name, as the selector for the field has that as primary sorting anyway.

    Pretty simple.. as always with these things, once you figure it out
     

    <?php
    
    $wire->addHookAfter("InputfieldAsmSelect(name=linked)::render", function ($event) {
      $html = $event->return;
    
      // Get the input field in order to sanitize new values
      /** @var Inputfield $input */
      $input = $event->object;
    
      // Create a DOMDocument object and load the html from the Inputfield
      $dom = new \DOMDocument;
      $dom->loadHTML($html);
    
      // Get the <select> and its childnodes
      $select = $dom->getElementsByTagName("select")->item(0);
      $options = $select->childNodes;
    
      // Keep track of the previous template name..
      $prevTemplate = '';
    
      //Loop through the childnodes
      for ($i = 0; $i < $options->length - 1; $i++) {
        $option = $options->item($i);
    
        if ($option && $option->attributes->getNamedItem('value')) {
    
          // Get the page onject
          $pageId = (int) $option->attributes->getNamedItem('value')->nodeValue;
          $page = $this->pages->get($pageId);
    
          // If a new template label is found..
          if ($prevTemplate !== $page->template->label) {
    
            // Create a new <option>
            $newOption = $dom->createElement("option");
            $newOption->setAttribute("disabled", true);
            $newOption->nodeValue = $input->entityEncode(mb_strtoupper($page->template->label));
    
            // And simply insert it above the current <option>
            $select->insertBefore($newOption, $option);
            $prevTemplate = $page->template->label;
          }
        }
      }
    
      // Return the new HTML and add a paragraph to double prove this bit of code do its work
      $event->return = $dom->saveHTML();
    });

    I'd love to be able to add things like icons, and some more formatting.. but for now: pretty decent.

     

    • Like 2
  6. Thanks for your replies! After @bernhard's suggestion I tried returning a completely custom bit of <select><optgroup><option ...></option><optgroup></select>.. but I would not render at all. So after all of this, it seems that asmSelect completely ignores the returned <select> from the function and replaces it with its own version. So there I bumped into what @Robin S wrote:

    12 hours ago, Robin S said:

    It's a shame, but AsmSelect doesn't support optgroups. It's not adding the optgroups to the underlying select markup that's the big problem, it's that AsmSelect doesn't account for optgroups when it builds the "fake" select from the underlying hidden select element. There was a pull request to add optgroup support the standalone jquery-asmSelect back in 2015 but it was never merged into either the standalone version or the InputfieldAsmSelect included in the PW core.

    So yeah.. clearly my idea will never work, unless Ryan decides to suddenly merge a request from 7 years ago on a project which hasn't been updated in 10 years.

    For now I've decided to leave it, and use InputfieldTextTags instead, which seems a bit more friendly visually. No optgroups there either, and no idea on how I would implement that either.

    Bummer!

  7. I have a very long list of pages inside a InputfieldSelectMultiple (InputfieldAsmSelect) dropdown, and I want to group the pages inside <optgroup>s, according to their template and some other features. But I can't get it to work.

    First of all, I think I can't get this done by the available options inside the Inputfield configuration (would love to be wrong here!) so I have taken the route of hooking into the Inputfield's render option. There, I would need to loop through all the <option>s, wrap these in their relevant <optgroup>s and return the result.

    1. So, I have done some testing, and made a proof of concept for myself on how to edit incoming HTML with a  <select>  in order to group its options inside <optgroup> tags.
    This stand-alone bit of code works perfectly fine:

    <?php
    
    // Create a snippet of HTML
    $html = "<p>
      <select>
        <option value='1'>Option #1</option>
        <option value='2'>Option #2</option>
        <option value='3'>Option #3</option>
        <option value='4'>Option #4</option>
      </select>
    </p>";
    
    // Create a DOMDocument object, and load the snippet
    $dom = new \DOMDocument;
    $dom->loadHTML($html);
    
    // Select the first <select> element from the HTML
    $select = $dom->getElementsByTagName("select")->item(0);
    
    // Create two option groups
    $optgroupEven = $dom->createElement("optgroup");
    $optgroupEven->setAttribute("label", "This is the even group");
    
    $optgroupOdd = $dom->createElement("optgroup");
    $optgroupOdd->setAttribute("label", "This is the odd group");
    
    // List through all the childnodes of the select
    $options = $select->childNodes;
    for ($i = $options->length - 1; $i >= 0; $i--) {
    
      // Get the current <option> inside the <select>
      $option = $options->item($i);
    
      // Some validation
      if ($option && $option->attributes->getNamedItem('value')) {
    
        // Remove from <select>
        $select->removeChild($option);
    
        // Prepend to odd or even optgroup
        // (Prepend because we list through the children in reverse)
        if ((int) $option->attributes->getNamedItem("value")->nodeValue % 2 === 0) {
          $optgroupEven->prepend($option);
        } else {
          $optgroupOdd->prepend($option);
        }
      }
    }
    
    // Add the groups to the <select>
    $select->appendChild($optgroupOdd);
    $select->appendChild($optgroupEven);
    
    // Add another option to the <select>
    $opt = $dom->createElement("option");
    $opt->nodeValue = "Option B";
    $select->appendChild($opt);
    
    echo "<h2>Original:</h2>";
    echo $html;
    
    echo "<h2>Grouped:</h2>";
    echo $dom->saveHTML();

    This results in what I would expect:

    310776944_Schermafbeelding2022-12-20om13_19_49.png.841b024b562632672d1f9159ed6d95b9.png

    1670791916_Schermafbeelding2022-12-20om13_19_55.png.8859d2343bca94e5568c146712d9c1a1.png

    Which proves the idea.

    2. I also know I can edit the output inside the page editor by hooking into the Inputfield's render function:

    <?php
    $wire->addHookAfter("InputfieldAsmSelect(name=linked)::render", function ($event) {
      $html = $event->return;
      $event->return = $html . "<p>This gets added!</p>";
    });

    1193839022_Schermafbeelding2022-12-20om12_47_35.png.2e9a7fd9c0faeac8cac2c84ae1a3b51d.png

    3. Trying to combine the two in a simple way without using <optgroup> also works. With the following bit of code I can easily add a new option to the Inputfield's <select>:

    <?php
    
    namespace ProcessWire;
    
    $wire->addHookAfter("InputfieldAsmSelect(name=linked)::render", function ($event) {
      $html = $event->return;
    
      // Get the input field in order to sanitize new values
      /** @var Inputfield $input */
      $input = $event->object;
    
      // Create a DOMDocument object and load the html from the Inputfield
      $dom = new \DOMDocument;
      $dom->loadHTML($html);
    
      // Get the <select>
      $select = $dom->getElementsByTagName("select")->item(0);
    
      // Create a new <option>, set label and value
      $opt = $dom->createElement("option");
      $opt->nodeValue = $input->entityEncode("This is a test, let's add this `option` to the `select`");
      $opt->setAttribute("value", 1);
    
      // Append to the <select>
      $select->appendChild($opt);
    
      // Return the new HTML and add a paragraph to double prove this bit of code do its work
      $event->return = $dom->saveHTML() . "<p>This gets added!</p>";
    });

    This yields the full <select> with my new <option> as the last element:

    1158663217_Schermafbeelding2022-12-20om13_04_56.jpg.9e8743fab0ee3dee852c70688cdb9b79.jpg

     

    4. Now here is my issue: I can't get <optgroup>'s to show up in the select. When I adapt my code above just a little bit, to incorperate <optgroup>, it just does not show up.
    The final paragraph does till get added though!

    <?php
    
    namespace ProcessWire;
    
    $wire->addHookAfter("InputfieldAsmSelect(name=linked)::render", function ($event) {
      $html = $event->return;
    
      // Get the input field in order to sanitize new values
      /** @var Inputfield $input */
      $input = $event->object;
    
      // Create a DOMDocument object and load the html from the Inputfield
      $dom = new \DOMDocument;
      $dom->loadHTML($html);
    
      // Get the <select>
      $select = $dom->getElementsByTagName("select")->item(0);
    
      // Create a new <option>, set label and value
      $opt = $dom->createElement("option");
      $opt->nodeValue = $input->entityEncode("This is a test, let's add this `option` to the `select`");
      $opt->setAttribute("value", 1);
    
      // Create an <optgroup>
      $optgroup = $dom->createElement("optgroup");
      $optgroup->setAttribute("label", "This is the optgroup");
      
      // Add the option to the optgroup
      $optgroup->prepend($opt);
    
      // Add the optgroup to the select
      $select->appendChild($optgroup);
    
      // Return the new HTML and add a paragraph to double prove this bit of code do its work
      $event->return = $dom->saveHTML() . "<p>This gets added!</p>";
    });

    A final screenshot would be useless, the whole optgroup and the option itself are both invisible now.

    Does anybody have an idea on how to get this to work?

    (Please note: I don't want to render a flat list with labels like {template} - {title}, that works technically but is problematic from a UX point of view).

     

     

     

  8. After enabling WebP support you may notice it can take a long time for ProcessWire to create WebP copies of all images and their variations.
    For instance, on a site I work on (with over 10k images), it was taking about 1 second per image, ie. more than 3 hours in total.. ?

    If you are comfortable around the command-line, you can use the cwebp program and this bash script to speed things up drastically.
    I have built upon this script and got things to work in combination with xargs and find, making it rather powerful for PW's purposes.

    1. Save this script as 'convert-webp.sh' (or download the Gist from Github), and follow instructions

    #########################################################################################################
    #
    # Fast Recursive Images to WebP converter
    # Customized for ProcessWire CMS/CMF <https://www.processwire.com>
    #
    # Author: Eelke Feenstra <dev@eelke.net>
    # Version: 001
    # Based upon: https://github.com/onadrog/bash-webp-converter
    #
    # Quick & dirty script to add webp versions to all PNG / JPG / JPEG files inside your PW assets folder
    #
    # 1. Set this script to executable:
    #       $ chmod +x convert-webp.sh
    #
    # 2. Check if cwebp is installed:
    #       $ cwebp -version
    #    If it is not, install:
    #       $ brew install webp
    #    Or follow instructions https://developers.google.com/speed/webp/download
    #    and change $executable to cwebp's full path
    #
    # 3. Run the script directly on a folder:
    #       $ ./convert-webp.sh /path/to/your/folder
    #
    #########################################################################################################
    
    #    Configuration
    
    executable="cwebp"    # update this to reflect your installation!
    quality=90            # change to desired WebP quality
    
    #########################################################################################################
    
    converted=0
    skipped=0
    
    echo "Entering $1"
    
    for file in $1/*
    do
        name="${file%.*}"
    
        echo "FILE: $file"
        echo "NAME: $name"
    
        # Skip the folder itself..
        if [ "$name" = "./." ]; then
            echo "SKIP: $name"
            continue;
        fi
    
        if [[ $(file --mime-type -b $name.webp) == image/webp ]]; then
    
            echo "FOUND: $name.webp, skipping.."
            skipped=$((skipped+1))
    
        elif [[ $(file --mime-type -b $file) == image/*g ]]; then
    
            echo "NOT FOUND: $name.webp"
    
            newfile(){
                echo "$file" | sed -r 's/(\.[a-z0-9]*$)/.webp/'
            }
    
            $executable -q $quality "$file" -short -o "$(newfile)"
            converted=$((converted+1))
        fi
    done
    
    echo "Converted $converted, Skipped $skipped"

    2. Run to create webp versions of all jpg/jpeg/png images in a given folder (for example the site's homepage)

    $ ./convert-webp.sh /path/to/processwire/site/assets/files/1

    3. And in order to create WebP copies of ALL images inside the /site/assets/files folder, you can run this script. It searches for all directories inside the files directory, and passes these to the convert-webp.sh script using xargs.

    $ find /path/to/processwire/site/assets/files -maxdepth 2 -type d | xargs -I '{}' ./convert-webp.sh '{}'

     

    Tested both on MacOS 12 and Debian

     

    • Like 5
  9. 19 hours ago, eelkenet said:

    I have reached out to the MAMP folks for info on how I could go about enabling it here.
    The only related issues on StackOverflow etc are pointing in the wrong direction it seems (homebrew etc).

     Update: The solution is to upgrade (paid) to MAMP PRO 6, this version comes with WebP support.
    The upgrade costs a lot less than all the time I've spent chasing this bug.. ?

    Edit: it took really long to convert all images, and I figured out a faster way using the command line. Read more in the tutorial.

     

    • Like 2
    • Haha 1
  10. @horst Oh my, I'm sorry for never replying to you! I think I have finally found the origin of my and @AndZyk's situation: MAMP PRO on MacOS (5.7) simply does not have WebP support enabled.

    I still don't know why this creates all the new copies, because it seems that all moving parts seem to be aware that webp is in fact not enabled. With this basic check:

    <?php
    
    namespace ProcessWire;
    
    include "index.php";
    error_reporting(E_ALL);
    ?>
    
    <pre>
    <h3>Check directly using gd_info()</h3>
    
    <?php
    $gd_info  = gd_info();
    $webpSupport = isset($gd_info['WebP Support']) ? $gd_info['WebP Support'] : false;
    print_r($gd_info);
    echo $webpSupport ? "\nWebP is supported" : "\nWebP is NOT supported";
    ?>
    
    
    <hr>
    <h3>ImageSizerEngineIMagick</h3>
    <?php
    $imagick = $modules->get("ImageSizerEngineIMagick");
    $supported = $imagick->supported("webp");
    echo $supported ? "WebP is supported" : "WebP is NOT supported";
    echo "\nFormats: " . print_r($imagick->getSupportedFormats(), true);
    ?>
    
    <hr>
    <h3>ImageSizerEngineGD</h3>
    <?php
    $gd = new ImageSizerEngineGD();
    $supported = $gd->supported("webp");
    echo ($supported ? "WebP is supported" : "WebP is NOT supported");
    echo "\nFormats: " . print_r($gd->getSupportedFormats(), true);
    ?>
    </pre>

    I get these results on my MAMP PRO machine:

    Check directly using gd_info()
    
    
    Array
    (
        [GD Version] => bundled (2.1.0 compatible)
        [FreeType Support] => 1
        [FreeType Linkage] => with freetype
        [GIF Read Support] => 1
        [GIF Create Support] => 1
        [JPEG Support] => 1
        [PNG Support] => 1
        [WBMP Support] => 1
        [XPM Support] => 
        [XBM Support] => 1
        [WebP Support] => 
        [BMP Support] => 1
        [TGA Read Support] => 1
        [JIS-mapped Japanese Font Support] => 
    )
    
    WebP is NOT supported
    
    
    ImageSizerEngineIMagick
    
    WebP is NOT supported
    Formats: Array
    (
        [source] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG24
                [3] => PNG
                [4] => GIF
                [5] => GIF87
            )
    
        [target] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG24
                [3] => PNG
                [4] => GIF
                [5] => GIF87
            )
    
    )
    
    
    ImageSizerEngineGD
    
    WebP is NOT supported
    Formats: Array
    (
        [source] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG
                [3] => GIF
            )
    
        [target] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG
                [3] => GIF
            )
    
    )

     

    And these on the online host:

    Check directly using gd_info()
    
    
    Array
    (
        [GD Version] => 2.2.5
        [FreeType Support] => 1
        [FreeType Linkage] => with freetype
        [GIF Read Support] => 1
        [GIF Create Support] => 1
        [JPEG Support] => 1
        [PNG Support] => 1
        [WBMP Support] => 1
        [XPM Support] => 1
        [XBM Support] => 1
        [WebP Support] => 1
        [BMP Support] => 1
        [TGA Read Support] => 1
        [JIS-mapped Japanese Font Support] => 
    )
    
    WebP is supported
    
    
    ImageSizerEngineIMagick
    
    WebP is supported
    Formats: Array
    (
        [source] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG24
                [3] => PNG
                [4] => GIF
                [5] => GIF87
            )
    
        [target] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG24
                [3] => PNG
                [4] => GIF
                [5] => GIF87
                [6] => WEBP
            )
    
    )
    
    
    ImageSizerEngineGD
    
    WebP is supported
    Formats: Array
    (
        [source] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG
                [3] => GIF
            )
    
        [target] => Array
            (
                [0] => JPG
                [1] => JPEG
                [2] => PNG
                [3] => GIF
                [4] => WEBP
            )
    
    )

    I have reached out to the MAMP folks for info on how I could go about enabling it here.
    The only related issues on StackOverflow etc are pointing in the wrong direction it seems (homebrew etc).

  11. Hi @Pete, could the minimum character count for the search on the forum please be reduced to 3 instead of (what I suspect) 4?

    It's really impractical to not be able to search for words like 'api', or 'get', while you know for sure that there must be many results for those words.

    • Like 2
  12. On 9/12/2021 at 11:31 AM, Chris-PW said:

    <a href="/OldName.pdf" download="NewName"> Download PDF</a>

    (The value "Filename" is optional.)

    Note: if you want to force a download but don't want to change the downloaded filename, you should omit the value of the download attribute like so: <a href="yourfile.pdf" download>link</a>

    • Like 1
  13. Hi @joshua, that works - sort of. When setting the user language inside a template we still only get the default language, as your hook gets called earlier. 

    However, what does work is hooking into the same Page::render method with a lower priority number, so our code gets an earlier execution. Great!

    In ready.php we now have:

    <?php
    
    namespace ProcessWire;
    
    // Hook into Page::render, just before PrivacyWire's hook 
    // Which uses the default priority of 100
    wire()->addHookBefore('Page::render', function (HookEvent $evt) {
    
      // Only apply to front-end pages
      $page = $evt->object;
      if (
        $page->template == 'admin' || // exclude admin pages
        $page->template == 'form-builder' // exclude from form-builder iframe
      ) {
        return;
      }
    
      $user = wire()->user;
      $languages = wire()->languages;
      
      // Get and sanitize the ?lang= get param
      $lang = strtolower(wire()->input->get("lang", "text"));
    
      // Set appropriate language
      if ($lang === "en") {
        $user->language = $languages->get("default");
      } else {
        $user->language = $languages->get("de");
      }
    }, ['priority' => 99]);

     

     

    • Like 2
  14. Hi, I've got a site that uses multi-language URLs based on a query-param, ie. https://example.com/some/page?lang=de.
    The site exists of a Vue.js app on top of a very basic HTML skeleton generated by PW, and we don't use the LanguageSupportPageNames module at all (so no example.com/de & example.com/en ).

    In order to set the initial skeleton HTML (such as page title etc), which gets rendered before the Vue app has booted, I set my $user->language based on the $input->get('lang') value. After the Vue app has booted, it takes over control and loads the remaining data in the appropriate language through a multilingual API endpoint.

    Next to the Vue app, we also use PrivacyWire.

    However, due to the way PrivacyWire has been built, it looks at the $users language BEFORE any of this takes place (in its ready() function).
    As a result, I can't get the correct language content inside the PrivacyWire popups, it always shows the default language content instead.

    So probably I need to hook into the getPrivacyWireConfigObject method, and overrule the PrivacyWire::lang variable with the language that I get from my $input->get('lang')?
    Or would there be another, easier approach?

    Any pointers would be most welcome! Thanks.

  15. Today I again bumped into an issue I had last year with creating WebP images:

    Enabling WebP on another project by setting  imageSizerOptions' webpAdd to true immediately resulted in the same behaviour as I had last year: the server simply keeps on creating new variations of images, while they already exist. WebP images are created correctly by the way.

    Seems to be a bug, can anybody else confirm? I am using PW Master (3.0.165) on MAMP Pro (MacOS 11.2, PHP 7.4.2)

     

  16. Hi @Sebi, I ran into a bug:

    Currently the Router::handleError() function incorrectly reports HTTP 500 errors that result from methods that should have remained silent, because they are called with the error control operator '@'.

    As the PHP documentation on error control operators puts it: 

    Quote

    If you have set a custom error handler function with set_error_handler() then it will still get called, but this custom error handler can (and should) call error_reporting() which will return 0 when the call that triggered the error was preceded by an @.

    I bumped into this while working on a project with some semi-broken images, where the APP API module kept throwing 500's from PW's ImageInspector class.
    Exif issues can be rather difficult to handle sometimes..

    The solution is simple: just add a check error_reporting() before the handleError method, for instance

      public static function handleError($errNo, $errStr, $errFile, $errLine)
        {
            if (error_reporting()) {
                $return = new \StdClass();
                $return->error = 'Internal Server Error';
                $return->devmessage = [
                    'message' => $errStr,
                    'location' => $errFile,
                    'line' => $errLine
                ];
                self::displayOrLogError($return, 500);
            }
        }

     

     

    • Like 2
  17. On 8/7/2020 at 11:52 AM, thomasaull said:
    • Caching with ProCache does not work with the current solution

    For what it is worth, I use this intermediate solution to use ProCache in combination with the RestAPI module:  https://processwire.com/talk/topic/20006-module-restapi/?do=findComment&comment=186881.

    Which gives me:
    1. site.url/rest-api => live data
    2. site.url/api => served by ProCache

    Of course this would only be useful for (static) pages that don't require any authentication or whatsoever. 

     

    • Like 2
×
×
  • Create New...