Jump to content

PHP 7.2.5


Dirty Butter

Recommended Posts

My Wordpress installs on the same domain with our stores has a notice that I should upgrade to php 7.2.5. Will I have any issues with CC 6.1.15 or 6.2.0 if I upgrade to php 7.2.5?

The only issue I found when testing 7.2.5 was a problem with the search edits that Bsmither had provided in catalogue.class.php:

Is there any way to improve customer SEARCH experience? - Page 3 - Technical Support - CubeCart Forums

While on 7.2.5 an attempt to search using the edits crashed the page. The error message:

[28-May-2018 13:38:55 America/Chicago] PHP Warning:  Illegal string offset 'I.name' in /home/butter01/public_html/plushcatalog/classes/catalogue.class.php on line 1941

I reverted to php 7.0 and the edited search worked again.

There may be other problems while using 7.5.2, but unless Bsmither or someone else can provide a patch to his Search edits, it looks like I'll have to stay on php 7.0 and let the WP sites complain.

 

Link to comment
Share on other sites

You suggested edits in two places:

	/**
	 * Search product catalog
	 *
	 * @param string $search_data
	 * @param int $page
	 * @param int $per_page
	 * @param string $search_mode
	 * @return bool
	 */
	// ORIGINAL B4 BSMITHER SEARCH CHANGE TO LIKE INSTEAD OF FULLTEXT public function searchCatalogue($search_data = null, $page = 1, $per_page = 10, $search_mode = 'fulltext') {
 public function searchCatalogue($search_data = null, $page = 1, $per_page = 10, $search_mode = 'rlike') {

And the main section:

                    /* BSMITHER SEARCH */
                    $this->_sort_by_relevance = false;
                    $rlike = '';
                    if (!empty($search_data['keywords'])) {
                                            $searchwords = preg_split( '/[\s,]+/', $GLOBALS['db']->sqlSafe($search_data['keywords']));
                        foreach ($searchwords as $word) {
                    if(empty($word) && !is_numeric($word)) continue;
                            if ((strtoupper($word) != 'AND') && (strtoupper($word) != 'OR')) $searchArray[] = $word;
                        }

                        $regexp = '';
                        $columnsToSearch = array(
                          'I.name',
                            'I.description',
                            'I.product_code',
                    'I.seo_meta_keywords',
                        );

                        foreach($columnsToSearch as $col) {
                            for ($i=0, $noKeys=count($searchArray); $i<$noKeys; ++$i) {
                                $regexp[$col][] = $col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'";
                            }
                            $regexp[$col] = '(' . implode(' AND ', $regexp[$col]) . ')';
                        }
                        $rlike = " AND (" . implode(' OR ', $regexp) . ")";
                    }
                    $q2 = "SELECT I.* FROM ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_inventory AS I LEFT JOIN (SELECT product_id, MAX(price) as price, MAX(sale_price) as sale_price FROM ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_pricing_group $group_id GROUP BY product_id) as G ON G.product_id = I.product_id $joinString WHERE I.product_id IN (SELECT product_id FROM `".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_category_index` as CI INNER JOIN ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_category as C where CI.cat_id = C.cat_id AND C.status = 1) AND I.status = 1 ".$whereString.$rlike;
                    $query = $q2.' '.$order_string.' '.$limit;
                    if (($search = $GLOBALS['db']->query($query)) !== false) {
                        $count = $GLOBALS['db']->query($q2, false, 0);
                        $this->_category_count  = (int)count($count);
                        $this->_category_products = $search;
                        return true;
                    }
                }
            }
        } else {
    /*     END OF BSMITHER SEARCH */
            if (is_numeric($search_data)) {
                if (($category = $this->getCategoryData((int)$search_data)) !== false) {
                    if (($products = $this->getCategoryProducts((int)$search_data, $page, $per_page)) !== false) {
                        $this->_category_products = $products;
                        return true;
                    }
                }

The line 1941 mentioned in the error message is

                                $regexp[$col][] = $col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'";

 

Link to comment
Share on other sites

PHP 7.1 has disallowed empty array index operator for strings.

This will cause numerous problems all over the world.

Regarding the above code, at least, make these changes and see what happens:

if ((strtoupper($word) != 'AND') && (strtoupper($word) != 'OR')) $searchArray[] = $word;

To:

if ((strtoupper($word) != 'AND') && (strtoupper($word) != 'OR')) $searchArray[] = [$word];

and:

$regexp[$col][] = $col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'";

To:

$regexp[$col][] = [$col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'"];

Note: putting the string inside brackets is the same as declaring the string as an array element using array().

 

Link to comment
Share on other sites

With changes 7.0 does not crash on search, but it does not find anything or give any notice to the customer. Error message:

     File: [catalogue.class.php] Line: [1950] "SELECT I.* FROM CubeCart_inventory AS I LEFT JOIN (SELECT product_id, MAX(price) as price, MAX(sale_price) as sale_price FROM CubeCart_pricing_group WHERE group_id = 0 GROUP BY product_id) as G ON G.product_id = I.product_id WHERE I.product_id IN (SELECT product_id FROM `CubeCart_category_index` as CI INNER JOIN CubeCart_category as C where CI.cat_id = C.cat_id AND C.status = 1) AND I.status = 1 AND ((Array AND Array) OR (Array AND Array) OR (Array AND Array) OR (Array AND Array)) " - Unknown column 'Array' in 'where clause'

Changing php to 7.2.5 - still crashes search results page with same error message:

[Exception] /home/butter01/public_html/plushcatalog/classes/catalogue.class.php:1941 - Cannot use string offset as an array

These changes were made and then  cache was emptied each time.

Just to be sure, since I'm bad about not correctly following directions:

                    /* NEW BSMITHER SEARCH */
                    $this->_sort_by_relevance = false;
                    $rlike = '';
                    if (!empty($search_data['keywords'])) {
                                            $searchwords = preg_split( '/[\s,]+/', $GLOBALS['db']->sqlSafe($search_data['keywords']));
                        foreach ($searchwords as $word) {
                    if(empty($word) && !is_numeric($word)) continue;
                           if ((strtoupper($word) != 'AND') && (strtoupper($word) != 'OR')) $searchArray[] = [$word];
                        }

                        $regexp = '';
                        $columnsToSearch = array(
                          'I.name',
                            'I.description',
                            'I.product_code',
                    'I.seo_meta_keywords',
                        );

                        foreach($columnsToSearch as $col) {
                            for ($i=0, $noKeys=count($searchArray); $i<$noKeys; ++$i) {
                               $regexp[$col][] = [$col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'"];
                            }
                            $regexp[$col] = '(' . implode(' AND ', $regexp[$col]) . ')';
                        }
                        $rlike = " AND (" . implode(' OR ', $regexp) . ")";
                    }
                    $q2 = "SELECT I.* FROM ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_inventory AS I LEFT JOIN (SELECT product_id, MAX(price) as price, MAX(sale_price) as sale_price FROM ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_pricing_group $group_id GROUP BY product_id) as G ON G.product_id = I.product_id $joinString WHERE I.product_id IN (SELECT product_id FROM `".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_category_index` as CI INNER JOIN ".$GLOBALS['config']->get('config', 'dbprefix')."CubeCart_category as C where CI.cat_id = C.cat_id AND C.status = 1) AND I.status = 1 ".$whereString.$rlike;
                    $query = $q2.' '.$order_string.' '.$limit;
                    if (($search = $GLOBALS['db']->query($query)) !== false) {
                        $count = $GLOBALS['db']->query($q2, false, 0);
                        $this->_category_count  = (int)count($count);
                        $this->_category_products = $search;
                        return true;
                    }
                }
            }
        } else {
    /*     END OF BSMITHER SEARCH */

 

Link to comment
Share on other sites

The original edits works with PHP 7.0.

Let's try this variant for PHP 7.1+:

if ((strtoupper($word) != 'AND') && (strtoupper($word) != 'OR')) $searchArray[] = $word;

To:

if ((strtoupper($word) != 'AND') && (strtoupper($word) != 'OR')) array_push($searchArray,$word);

and:

$regexp[$col][] = $col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'";

To:

array_push($regexp[$col],$col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'");

It seems the first variant was adding an array to an array. My bad.

But know this: With PHP7.1+, there are a number of statements that will crash PHP -- once you start adding conditions found in the Advanced Search.

Link to comment
Share on other sites

This new edit does not crash. It works on 7.0. But on 7.2.5 it gives no results for the search. SORRY - IT DOES NOT FIND RESULTS ON 7.0.

Error message :

File: [catalogue.class.php] Line: [1949] "SELECT I.* FROM CubeCart_inventory AS I LEFT JOIN (SELECT product_id, MAX(price) as price, MAX(sale_price) as sale_price FROM CubeCart_pricing_group WHERE group_id = 0 GROUP BY product_id) as G ON G.product_id = I.product_id WHERE I.product_id IN (SELECT product_id FROM `CubeCart_category_index` as CI INNER JOIN CubeCart_category as C where CI.cat_id = C.cat_id AND C.status = 1) AND I.status = 1 AND () ORDER BY `stock_level` DESC LIMIT 12 OFFSET 0 " - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') ORDER BY `stock_level` DESC LIMIT 12 OFFSET 0' at line 1

Can I test this on a 6.2.1 test site instead of my live store? I'm swapping back and forth each time to keep plushcatalog as usable as possible.

Link to comment
Share on other sites

Hm. Now it's not getting any of the arrays.

Be back soon.

 

Find:
                    /* NEW BSMITHER SEARCH */
                    $this->_sort_by_relevance = false;
                    $rlike = '';

Change to:

                     /* NEW BSMITHER SEARCH */
                    $this->_sort_by_relevance = false;
                    $rlike = ''; $searchArray = []; $regexp = [];


A few lines down, delete:

$regexp = '';

 

Link to comment
Share on other sites

Same situation - not crashing, but not finding:

File: [catalogue.class.php] Line: [1949] "SELECT I.* FROM CubeCart_inventory AS I LEFT JOIN (SELECT product_id, MAX(price) as price, MAX(sale_price) as sale_price FROM CubeCart_pricing_group WHERE group_id = 0 GROUP BY product_id) as G ON G.product_id = I.product_id WHERE I.product_id IN (SELECT product_id FROM `CubeCart_category_index` as CI INNER JOIN CubeCart_category as C where CI.cat_id = C.cat_id AND C.status = 1) AND I.status = 1 AND (() OR () OR () OR ()) ORDER BY `stock_level` DESC LIMIT 12 OFFSET 0 " - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') OR () OR () OR ()) ORDER BY `stock_level` DESC LIMIT 12 OFFSET 0' at line 1

I'm getting off for the  night - I appreciate your efforts, but I'll go back to 7.0 for now and be fresh to work on it hopefully when you have the time.

Link to comment
Share on other sites

Very odd indeed. Based on your GitHub report about php 7.1+ it sounded to me like LOTS of files would be effected in CC, not just this edited search. https://github.com/cubecart/v6/issues/2049

I have test sites on the latest commit of 6.2.1. If you want to pursue this search situation, I'd like to test on those, not 6.1.15 plushcatalog, if possible.

If this coding style is throughout CC, I probably just need to ignore the WP notice until CC is ready for 7.1+.

 

Link to comment
Share on other sites

19 hours ago, Dirty Butter said:

My Wordpress installs on the same domain with our stores has a notice that I should upgrade to php 7.2.5. Will I have any issues with CC 6.1.15 or 6.2.0 if I upgrade to php 7.2.5?

it looks like I'll have to stay on php 7.0 and let the WP sites complain.

We are running plenty of CubeCart sites on PHP 7.1 and PHP 7.2 and havent noticed any issues or had any reported by clients - in fact, on the servers we use for our Fully Managed CubeCart hosting, we only offer 7.1 and 7.2 !    PHP 5.6 and 7.0 are coming to end of life later this year and we are pushing clients to move to 7.1 or ideally 7.2 ASAP - as soon as they reach end of life, we will be removing them from most of our servers due to increasing security risks

Link to comment
Share on other sites

Interesting! I didn't keep testing for any other issues caused by 7.2.0 once I found this one that is very important to our site. I'll kick the tires today on the 6.2+ CC test sites with php 7.2 installed in earnest and see if that's the only problem.

Link to comment
Share on other sites

Bsmither - I'm in the process of double checking all my edited areas and comparing to stock 6.2+ files. I noticed there is another place in catalogue.class.php that you had me change with the edited Search code in use with 6.1.15 -

			// STOCK	if($search_mode == 'fulltext') { 
					$max_word_len = $GLOBALS['db']->getSearchWordLen();
					$words = explode(' ', $search_data['keywords']);
					if (is_array($words)) {
						$search_str_len = 0;
						foreach ($words as $word) {
							$search_str_len = ($search_str_len < strlen($word)) ? strlen($word) : $search_str_len;
						}
					} else {
						$search_str_len = strlen($search_data['keywords']);
			// STOCK		}  

Is this why I wasn't getting any results, even when it did not crash?

 

Link to comment
Share on other sites

  • 1 month later...

Coming back to this issue due to Havenswift's stated intention to upgrade all his servers to 7.1 or 7.2. I really don't want to lose the fantastic Search function Bsmither developed that is working on php 7.0. But I don't want to stay on CC6.1.15 in order to keep the search working.

I now have today's current commit CC6.2.1+ installed on the live site dirtybutterestates.com. The Bsmither Search is crashing the site, but I haven't yet found anything else that is not working with php7.1 installed.

Link to comment
Share on other sites

Did I really suggest this?

// STOCK    if($search_mode == 'fulltext') {

and

// STOCK    }

Putting in double slashes makes what follows in THAT line a comment. Meaning, the following lines will be executed. They have not been commented out.

IF I suggested removing that entire section of code - which you chose to keep as a reference - then the proper way would be:

/* STOCK Code follows
            if($search_mode == 'fulltext') {

and

            }
End of STOCK Code */

IF I actually suggested commenting out those two specific lines of code, then, well, OK.

Link to comment
Share on other sites

I understood it to be just those two lines - not all in between.

 

This seems to be the part of your version that is causing the warning:

					    $regexp = '';
					    $columnsToSearch = array(
					      'I.name',
					        'I.description',
					        'I.product_code',
					'I.seo_meta_keywords',
					    );

					    foreach($columnsToSearch as $col) {
					        for ($i=0, $noKeys=count($searchArray); $i<$noKeys; ++$i) {
	LINE 1950				            $regexp[$col][] = $col."  RLIKE '[[:<:]]".$searchArray[$i]."[[:>:]]'";

PHP Warning:  Illegal string offset 'I.name' in XXX/public_html/dirtybutterestates.com/classes/catalogue.class.php on line 1950

 

 

Link to comment
Share on other sites

I am going to say, that by CC621, much of all this recoding has been implemented as stock.

If true, the only thing left to do is to start the function with:

public function searchCatalogue($search_data = null, $page = 1, $per_page = 10, $search_mode = 'rlike') {

instead of 'fulltext'.

But, I will review these conversations to determine if there was anything specific these changes were to accomplish.

The problem with line 1950 is PHP 7.1 no longer allows for a variable to be declared a string (see 10 lines earlier), then start pushing arrays onto it. So, we can't use that section of code.

Link to comment
Share on other sites

What makes your code so different from stock is the part about narrowing choices down no matter what order the terms are searched for.

Your code on dirtybutter/plushcatalog makes a search for dog puppet blue give the exact same results as puppet blue dog or for blue dog puppet.

Link to comment
Share on other sites

Let's try this. Line numbers are for CC621:

If you want to start with RLIKE, bypassing FULLTEXT:

Line 1612:
public function searchCatalogue($search_data = null, $page = 1, $per_page = 10, $search_mode = 'rlike') {

Line 1845, find:
$noKeys = count($searchArray);

On the blank line ABOVE that, add:
/* ORIGINAL Code follows

Line 1873, find the statement that STARTS WITH:
$q2 = "SELECT I.* FROM ".$GLOBALS['config']->get('config', 'dbprefix')

On the blank line ABOVE that, add:
   ORIGINAL Code above ends here */
						$noKeys = count($searchArray);
						$regexp = $regexp_desc = array();
						$columnsToSearch = array('I.name','I.product_code','I.seo_meta_keywords',); // columns where contents are plain words
						$columnsToSearch_desc = array('I.description',); // columns where contents can be rich text
						$search_mode = in_array($search_mode, array('rlike','like')) ? $search_mode : 'rlike';

						if($search_mode == 'rlike') {
							$like_keyword = "RLIKE";
							$like_prefix = '[[:<:]]';
							$like_postfix = '[[:>:]]';
						} else {
							$like_keyword = "LIKE";
							$like_prefix = '%';
							$like_postfix = '%';
						}
						foreach($columnsToSearch as $col) {
							for ($i=0; $i<$noKeys; ++$i) {
								$ucSearchTerm = strtoupper($searchArray[$i]);
								if (($ucSearchTerm != 'AND') && ($ucSearchTerm != 'OR')) {
									$regexp[$col][] = $col." ".$like_keyword." '".$like_prefix.$searchArray[$i].$like_postfix."'";
								}
							}
							$regexp[$col] = '('.implode(' AND ', $regexp[$col]).')';
						}
						foreach($columnsToSearch_desc as $col) {
							for ($i=0; $i<$noKeys; ++$i) {
								$ucSearchTerm = strtoupper($searchArray[$i]);
								if (($ucSearchTerm != 'AND') && ($ucSearchTerm != 'OR')) {
									$regexp_desc[$col][] = $col." ".$like_keyword." '".$like_prefix.htmlentities(html_entity_decode($searchArray[$i],ENT_COMPAT,'UTF-8'),ENT_QUOTES,'UTF-8',false).$like_postfix."'";
								}
							}
							$regexp_desc[$col] = '('.implode(' AND ', $regexp_desc[$col]).')';
						}
						$like = ' AND ('.implode(' OR ', $regexp).' OR '.implode(' OR ', $regexp_desc).')';
					}

This will create a query that looks like the following, searching for the whole words robot and dog:

SELECT I.* FROM CubeCart_inventory AS I 
LEFT JOIN (SELECT product_id, MAX(price) as price, MAX(sale_price) as sale_price FROM CubeCart_pricing_group 
           WHERE group_id = 1 GROUP BY product_id) as G 
ON G.product_id = I.product_id  
WHERE I.product_id IN (SELECT product_id FROM `CubeCart_category_index` as CI 
                       INNER JOIN CubeCart_category as C where CI.cat_id = C.cat_id AND C.status = 1)
AND I.status = 1  
AND ((I.use_stock_level = '0') OR (I.use_stock_level = '1' AND I.stock_level > 0)) 
AND (
      (I.name RLIKE '[[:<:]]robot[[:>:]]' AND I.name RLIKE '[[:<:]]dog[[:>:]]')
   OR (I.product_code RLIKE '[[:<:]]robot[[:>:]]' AND I.product_code RLIKE '[[:<:]]dog[[:>:]]') 
   OR (I.seo_meta_keywords RLIKE '[[:<:]]robot[[:>:]]' AND I.seo_meta_keywords RLIKE '[[:<:]]dog[[:>:]]') 
   OR (I.description RLIKE '[[:<:]]robot[[:>:]]' AND I.description RLIKE '[[:<:]]dog[[:>:]]')
) 
ORDER BY updated ASC LIMIT 12 OFFSET 0 

Note that the search is on ANY of name, product_code, seo_meta_keywords, or description, where ALL searched words must be present.

Also recall that if no results are found using RLIKE, CubeCart tries this again using the sloppier LIKE syntax.

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...