We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 15001
    • 697 Posts
    Hi,

    How to allow database request in such case?

    Document 1 --loads--> Javascript --ajax request--> Document 2 --contains--> Snippet --includes--> PHP snippet class --call--> Method --request--> MODx table

    This works if I logged in the MODx manager (via another tab) prior Document 1 was loaded. Else, the database request fails.

    Example case: TreasureChest initilializing process
    Product page --loads--> treasurechest.js --"ajax ’config’ request--> Cart document --contains--> [!TreasureChest? &service=`cart` ...!] --includes--> treasurechest.class.php --call--> $Cart->TreasureConfig() --request--> treasure_chest_config

    This request to the "config" table is necessary to get the name of several classes defined in the module configuration that we need to make the client side javascript work.

    I tried adding this code at the beginning of the snippet:
        
    require_once $modx->config['base_path'].'manager/includes/config.inc.php';
    require_once $modx->config['base_path'].'manager/includes/protect.inc.php';
    require_once $modx->config['base_path'].'manager/includes/document.parser.class.inc.php';
    //$modx = new DocumentParser;
    $modx->db->connect(); // provide the MODx DBAPI
    $modx->getSettings(); // provide the $modx->documentMap and user settings

    (cf. http://wiki.modxcms.com/index.php/Use_AJAX_with_modxAPI)

    I also tried calling the connect and deconnect dbapi functions from the TreasureConfig() method, but this was worse as MODx displayed a blank page instead of the normal content.
    // Return a PHP associative key-value array built from the data 
    // in the general TreasureChest Configuration settings
    // Function by Scotty Delicious
    
    function TreasureConfig()
    {
        global $modx;
        //$modx->db->connect('localhost', 'database_name', 'database_user', 'password', true);
    
        $config_table = $modx->getFullTableName('treasure_chest_config');	// Retrieve the full table of general TreasureChest settings
        $config = $modx->db->query("SELECT * FROM ".$config_table);
    
        $config_array = array();
        while ($row = $modx->db->getRow($config, 'assoc'))
        {	
            // The table column for keys :
        	// some values of the "setting_name" column have a "store_" prefix. We remove it.
            $key = str_replace('store_', '', $row['setting_name']);
            
            // The table column for values: decode values.
            $val = htmlspecialchars_decode($row['setting_value']);
            
            // Sets the php "$config_array[]" associative array from the table.
            $config_array[$key] = $val; 
        }
        //$modx->db->disconnect()
        return $config_array;		// Return the array.
    }


    Thanks for your help.

    Julien

    P.S.: Demo available if necessary.
      • 22303 MODX Staff
      • 10,725 Posts
      You create one Resource for the page and one for the AJAX request; each has it’s own Snippet( s ).
        • 15001
        • 697 Posts
        Hi Jason,

        Sorry to ask so stupid question, but what do you mean by "Ressource".
        Document?

        If yes, this is already the case. Currently, the two documents (page + "cart" document) have their own snippet, and the Ajax request is performed from the product page to the cart document.

        The snippet call in the cart document retrieves this parameter to perform the appropriate action. What I observed it that the snippet on the ajax-called page it is able to select the correct object method. But then, the query on the database fails, unless I’m simultaneously connected to the MODx manager.

        I’m very surprised by this difference in connected VS disconected modes. Is this normal?

        Thanks a lot.

        Julien
          • 22303 MODX Staff
          • 10,725 Posts
          Sounds like maybe you have not published your AJAX Resource.
            • 15001
            • 697 Posts

            If only! Unfortunately, this is not the case. The document called by Ajax is published. The Treasurechest snippet called by this document is of course inside MODx.

            I temporarily gave 777 a permission to the treasurechest.class.php file, which is included by the snippet. This file defines the class that powers the ecommerce system. This did not change anything.

            Currently, I’m planning to call by Ajax a distinct PHP file which would set the database connection, extract and return the necessary data.

            Jason, I wanted to create you a manager account so that you can see the problem, but I cannot edit the role as the checkboxes are greyed.
            (see http://modxcms.com/forums/index.php/topic,42194.msg295012.html#msg295012)

              • 22303 MODX Staff
              • 10,725 Posts
              TreasureChest handles AJAX requests?! I would assume you would have to create your own AJAX-handling snippet. Did you make sure the Content Type was correct? And that there is no template corrupting whatever AJAX results you are attempting to return?

              IMO, you should never ever create AJAX requests as external files that way; you are asking for problems, including the potential to create an attack vector into your MODx system. Focus on figuring out your problem with the AJAX resource/snippet you have created.

              As for TreasureChest, I am not familiar, so afraid I’m not going to be any help on specifics there.
                • 15001
                • 697 Posts
                TreasureChest handles AJAX requests?!

                TreasureChest performs several Ajax requests though "treasurechest.js".
                This file is automatically added by the server component of TreasureChest by using the MODx API to register treasurechest.js as startup script.

                The Ajax requests are performed trough the jQuery library, which is itself included in treasurechest.js. (Of course it can be removed from the file if you import it another way.)

                Many Ajax requests were already present in TreasureChest 1.0. They were used to initialize the cart, to build the cart view in the thickbox, to remove one product from the cart view, to handle changes in product options, to ask if the "View cart" and "Empty cart" buttons should be visible or not, a.s.o. Most Ajax requests were performed through the $.post() jQuery command which is a shortcut for $.ajax().

                With TreasureChest 1.1 and upper, most commands were switched from $.post() to $.ajax() as $.post() presented two major draw major drawbacksgs embedded carts. Firstly, it $.post() runs Ajax requests asynchroneously, which is problematic in certain situations. Secondly, it caches the returned content and this was also problematic.

                TreasureChest 1.1 and 1.2 also added new Ajax requests, especially for the in-page embedded cart and the button "-1" (i.e. "Remove one").

                If you’re interested to see what TreasureChest 1.2 can do, here are several screenshots. The tif and png images are the same, but the png ones are faster to load. http://www.altipoint.ch/preview/copies_ecran_treasurechest/

                I would assume you would have to create your own AJAX-handling snippet. Did you make sure the Content Type was correct? And that there is no template corrupting whatever AJAX results you are attempting to return?

                Yes, absolutely, the content is correct. The best proof if that the returned content is OK when I’m logged into the MODx manager. It was also easy to check it with an "alert();" displaying the data returned. Lasty, I’ve configured Firebug to show Ajax things in its "Console" tab. So, I can easily check the returned data.

                The problem is server side. I’m absolutely sure about it. I observed it by making my script write a file on server side. In that file, it writes the data that should be returned, just before the json_encode() PHP function is called.
                I’ll tell at the end of this message what’s going wrong when I’m not connected to MODx.

                IMO, you should never ever create AJAX requests as external files that way; you are asking for problems, including the potential to create an attack vector into your MODx system.

                Do you mean that I should not use an external PHP file to handle the Ajax request and put all code in the snippet? I totally agree, but for debugging purposes, it can be useful to isolate things temporarily outside of MODx.

                As for TreasureChest, I am not familiar, so afraid I’m not going to be any help on specifics there.

                I understand, but the problem is not specific to TreasureChest.

                Now, what I observed is that the records of the database table are read several times.
                After the table is read, something loops and the records are read again and again.
                This leads to a buffer overflow.

                For the debugging, I exported the content of the problematic function in a distinct PHP file and added the necessary files for the API to work. Here’s this PHP file (with modified credentials!).
                <?php
                
                define('MODX_MANAGER_PATH', '../../../manager/');  //relative path for manager folder
                require_once(MODX_MANAGER_PATH . 'includes/config.inc.php');//config
                
                // Setup the MODx API
                define('MODX_API_MODE', true);
                
                // initiate a new document parser (maybe not necessary)
                include_once(MODX_MANAGER_PATH.'/includes/document.parser.class.inc.php');
                $modx = new DocumentParser;
                 
                $database_server = 'localhost';
                $database_name = 'serveraccount_modxsite';
                $database_user = 'serveraccount_thedbaseuser';
                $database_password = 'somepassword';                                                                                     
                $modx->db->connect($database_server, $database_name, $database_user, $database_password, true);   
                
                // Return a PHP associative key-value array built from the data in the general TreasureChest Configuration settings                
                
                // Retrieve the full table of general TreasureChest settings.
                $config_table = $modx->getFullTableName('treasure_chest_config');	//Add prefix
                $config = $modx->db->query("SELECT * FROM ".$config_table);  // For simplicity :-)                                                                
                                                                                                                                              
                $config_array = array();  
                $simpleOutput = '';                                                                                                    
                while ($row = $modx->db->getRow($config, 'assoc'))                                                                            
                {	                                                                                                                            
                    // The table column for keys :                                                                                               
                	  // some values of the "setting_name" column have a "store_" prefix. We remove it.                                            
                    $key = str_replace('store_', '', $row['setting_name']);                                                                   
                                                                                                                                              
                    // The table column for values: decode values.                                                                            
                    $val = htmlspecialchars_decode($row['setting_value']);                                                                    
                                                                                                                                              
                    // Sets the php "$config_array[]" associative array from the table.                                                       
                    $config_array[$key] = $val;   
                    
                    $toto .= $toto.$key.$val;                                                                                            
                }                                                                                                                             
                $modx->db->disconnect();                                                                                                     
                // $json_string = json_encode($config_array);	 ' fails
                echo $simpleOutput;
                ?>


                Looks like the while() starts again at top of table when the user is not logged in the MODx manager.


                  • 36416
                  • 589 Posts
                  Quote from: Jul at Jun 20, 2010, 11:37 AM

                  For the debugging, I exported the content of the problematic function in a distinct PHP file and added the necessary files for the API to work. Here’s this PHP file (with modified credentials!).

                  Hmm, why are you connecting with different credentials?
                  Does the other user have enough privileges to read all MODx tables?
                    • 15001
                    • 697 Posts
                    Hi,
                    I’m not connecting with different credentials. Just connecting the database directly and using the MODx API functions. What I meant by "modified credentials" is that I’ve not posted the true database name, user name and password to the forum. wink
                      • 36416
                      • 589 Posts
                      Quote from: Jul at Jun 21, 2010, 01:26 AM

                      I’m not connecting with different credentials. Just connecting the database directly and using the MODx API functions. What I meant by "modified credentials" is that I’ve not posted the true database name, user name and password to the forum. wink

                      Ah, now I understand. But then you can optimize your code by connecting with default credentials (i.e. without duplication of DBname, username...):
                      $modx->db->connect();


                      BTW, sorry that I can’t help with the original problem.