On March 26, 2019 we launched new MODX Forums. Please join us at the new MODX Community Forums.
Subscribe: RSS
  • Hello,

    I need to integrate a 3rd party booking system search bar and have been provided with the code to do this, which contains 2 php calls which load further JS. I can test run this locally fine in standard php via MAMP but can't get anything loading in MODX when using snippets to call the provided php.

    The following is what I’ve been provided with (I changed the domain name here).

    This loads a form and fetches a JS file:
    <?php
    echo file_get_contents("http://accommodation.thedomainname.com/rentals/formularioMiniOptimized.php?bk=bk_thedomainname&Idioma=EN&Fajax=1");
    ?>


    This just loads a bunch of external JS assets:
    <?php
    echo file_get_contents("http://accommodation.thedomainname.com/rentals/includeJs.php?bk=bk_thedomainname&tipo=formulario");
    ?>


    Firstly I changed 'echo' to 'return' and then just added the 2 code blocks verbatim into a couple of new snippets respectively, however, when I call these snippets I'm getting zero return. I've tried calling them cached/uncached but with no joy. Both snippets do actually work as I added a simple text string which renders fine.

    Can anyone advise on how I can get a return from these snippets with the code provided?

    For the record I have tried this whole shebang with only the form and external JS assets, i.e. without the need for any php call/snippets, plus loading the JS more performantly. But that is throwing console errors and various other malarkey so I’m looking at the original suggestion.

    Here's the build setup:
    MODX Revolution: 2.5.7-pl (traditional)
    PHP Version: 5.6.30
    MySQL Client API version: mysqlnd 5.0.11-dev (from phpinfo file)
    Database client version: libmysql - 5.1.73 (from phpMyAdmin)
    Server version: 5.6.35 - MySQL Community Server (GPL) (from phpMyAdmin)
    Protocol version: 10

    Thanks in advance.
    • You should always use return rather then echo in MODX snippets.

      file_get_contents is not always enabled for URLs.

      If not, you can always use fopen(), or if that doesn't work, cURL.

      Here's a function I use to get content from a remote site,

      // $url - URL of remote site
      // $path - location to save results
      // $method - 'fopen' or 'curl' -- I find curl more reliable
      // $certPath - path to local copy of the cert file - may be necessary if 
      
      function downloadFile($url, $path, $method, $certPath = null)
          {
              $newfname = $path;
              if (file_exists($path)) {
                  unlink($path);
              }
              $newf = null;
              $file = null;
              if ($method == 'fopen') {
                  try {
                      $file = fopen($url, "rb");
                      if ($file) {
                          $newf = fopen($newfname, "wb");
                          if ($newf) {
                              set_time_limit(0);
                              while (!feof($file)) {
                                  fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
                              }
                          } else {
                              return ('Could not open ' . $newf . ' for writing');
                          }
                      } else {
                          return ('fopen failed to open ' . $url);
                      }
                  } catch (Exception $e) {
                      return 'ERROR:Download ' . $e->getMessage();
                  }
                  if ($file) {
                      fclose($file);
                  }
                  if ($newf) {
                      fclose($newf);
                  }
      
              } elseif ($method == 'curl') {
                  $newf = fopen($path, "wb");
                  if ($newf) {
                      set_time_limit(0);
                      $ch = curl_init(str_replace(" ", "%20", $url));
                      if ($certPath !== null) {
                          curl_setopt($ch, CURLOPT_CAINFO, $certPath); 
                      }
                      // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);  // uncomment for better security (may require $certPath)
                      // curl_setopt($ch, CURLOPT_SSL_PEER, 1);  // uncomment for better security (may require $certPath)
                      curl_setopt($ch, CURLOPT_TIMEOUT, 180);
                      curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0)');
                      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                      curl_setopt($ch, CURLOPT_FILE, $newf);
                      $openBasedir = ini_get('open_basedir');
                      if (empty($openBasedir) && filter_var(ini_get('safe_mode'),
                              FILTER_VALIDATE_BOOLEAN) === false) {
                          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                      } else {
                          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
                          $rch = curl_copy_handle($ch);
                          curl_setopt($rch, CURLOPT_URL, $url);
                          $header = curl_exec($rch);
                          if (!curl_errno($rch)) {
                              $newurl = $url;
                              $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
                              if ($code == 301 || $code == 302) {
                                  if (version_compare(PHP_VERSION, '5.3.7') < 0) {
                                      preg_match('/Location:(.*?)\n/i', $header, $matches);
                                      $newurl = trim(array_pop($matches));
                                  } else {
                                      $newurl = curl_getinfo($rch, CURLINFO_REDIRECT_URL);
                                  }
                              }
                              curl_close($rch);
                              curl_setopt($ch, CURLOPT_URL, $newurl);
                          }
                      }
                      $retVal = curl_exec($ch);
                      if ($retVal === false) {
      
                          return ('cUrl download failed ' . curl_error($ch));
                      }
                      curl_close($ch);
                  } else {
                      return ('Cannot open ' . $path . ' for writing');
                  }
              } else {
                  return 'Invalid method in call to downloadFile()';
              }
      
              return file_get_contents($path);
          }
      
          return downloadFile(...);


      During development, it's nice to have the file saved so you can look at it. Once it's working, you could just return the content and remove one of the two methods. [ed. note: BobRay last edited this post 1 year, 11 months ago.]
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
      • Thanks for this, much appreciated.

        I had used 'return' over 'echo' in my first attempt but got zilch.

        In terms of the php, for utilising one of the methods/removing the other (and negating the need for the 'if' statement) I'm unsure of the syntax to use for the method call. So for example using 'fopen' would it be as a method parameter like this:
        {
                $newfname = $path;
                if (file_exists($path)) {
                    unlink($path);
                }
                $newf = null;
                $file = null;
                $method('fopen') { 
                        ... 
                }
        }
        

        or like this:
        {
                $newfname = $path;
                if (file_exists($path)) {
                    unlink($path);
                }
                $newf = null;
                $file = null;
                $method == 'fopen' { 
                        ... 
                }
        }
        

        or something else!

        And I'm not sure what you mean here:
        return (downloadFile(...);

        For the record, I got the page in question working as I grabbed all the JS manually and managed to reduce a few http requests in the process. However, I would like to achieve this way of utilising external file loading via MODX snippets so if you could advise that would be appreciated.

        Thanks
        • Here's the basic structure of the function:

          if ($method == 'fopen') {
             /* code */
          } elseif ($method == 'curl') {
             /* code */
          } else {
            return 'Invalid method in call to downloadFile()';
          }
          


          If you want to use fopen, remove the //-commented lines below:

          // if ($method == 'fopen') {
             /* code */
          // } elseif ($method == 'curl') {
          //   /* code */
          // } else {
          //   return 'Invalid method in call to downloadFile()';
          // }
          


          If you want to use cURL, remove the //-commented lines below

          // if ($method == 'fopen') {
          //    /* code */
          // } elseif ($method == 'curl') {
             /* code */
          // } else {
          // return 'Invalid method in call to downloadFile()';
          // }
          


          This line calls the downloadFile() function and returns what it returns (the string containing the content retrieved from the URL). The code I posted above has an extra '()' at the beginning and end of that line (my bad - holdover from using C++ for many years).

          return downloadFile(...);


          It might make more sense to you like this, which will do the same thing:

          $output =  downloadFile(...);
          return $output;
          



            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting
          • Thanks for this and apologies for this tardy reply.
            So far I've not integrated it as I solved it via JS. However, I will hit this as soon as I can stop chasing my tail!