Jump to content
Sign in to follow this  
Dirty Butter

PHP 7.2.5

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.

 

Edited by Dirty Butter

Share this post


Link to post
Share on other sites

Please copy from your edited version of catalogue.class.php lines 1931 through 1951.

Share this post


Link to post
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]."[[:>:]]'";

 

Share this post


Link to post
Share on other sites

Sorry, I realized you needed to know that and had already added it to the end of the post. I miss the old forum code that showed the line numbers!

Share this post


Link to post
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().

 

Share this post


Link to post
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 */

 

Share this post


Link to post
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.

Edited by bsmither

Share this post


Link to post
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.

Edited by Dirty Butter

Share this post


Link to post
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 = '';

 

Edited by bsmither

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

Here's a weird one -- I have CC620B1 on PHP 7.2.4, and I have no issues with the code that I am sure would have caused a problem.

 

Share this post


Link to post
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+.

 

Share this post


Link to post
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

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

So, something in my alternate search code is not liking PHP7.1+
"Cannot use string offset as an array"

Then the crazy results when using the more concrete function array_push().

Share this post


Link to post
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?

 

Share this post


Link to post
Share on other sites

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.

Edited by Dirty Butter

Share this post


Link to post
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.

Edited by bsmither

Share this post


Link to post
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

 

 

Edited by Dirty Butter

Share this post


Link to post
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.

Share this post


Link to post
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.

Share this post


Link to post
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.

 

Edited by bsmither

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...