Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

A Store Speed Optimization in Progress


Guest

Recommended Posts

Hi!

I have a serious issue:)

 

I did read alot of the great tips/posts here and trying optimize the speed of the site constantly for more than a week now, I reduce the webbsite download time a bit..but it is still very slow

 

We want to release the site soon, but first I need to enhance the speed...so this is making me crazy:)

I have installed the KISS debugging, so you will se that result on the screen at my site www.stylingagenten.se

 

When I put up the site at http://analyze.websiteoptimization.com I got this result: (As you see it has serious download problems)

 

Object type Size (bytes) Download @ 56K (seconds) Download @ T1 (seconds)

HTML: 11798 2.75 0.46

HTML Images: 224562 52.55 8.99

CSS Images: 142594 46.22 18.56

Total Images: 367156 98.77 27.55

Javascript: 41608 9.09 1.02

CSS: 21358 4.86 0.71

Multimedia: 0 0.00 0.00

Other: 0 0.00 0.00

 

 

Do you have any clue why my site StylingAgenten.se is so slow? All the underpages are also slow...:(

 

I guess the size of the files above has a part of the problem I have not fins any way yet to reduce them thou...

 

I did follow some tips here and compremized the .js and .css files. I also use Gzip comression.

 

Please help me!

 

Best Regards

Andreas

Link to comment
Share on other sites

  • Replies 905
  • Created
  • Last Reply

Hi!

I have a serious issue:)

 

I did read alot of the great tips/posts here and trying optimize the speed of the site constantly for more than a week now, I reduce the webbsite download time a bit..but it is still very slow

 

We want to release the site soon, but first I need to enhance the speed...so this is making me crazy:)

I have installed the KISS debugging, so you will se that result on the screen at my site www.stylingagenten.se

 

When I put up the site at http://analyze.websiteoptimization.com I got this result: (As you see it has serious download problems)

 

Object type Size (bytes) Download @ 56K (seconds) Download @ T1 (seconds)

HTML: 11798 2.75 0.46

HTML Images: 224562 52.55 8.99

CSS Images: 142594 46.22 18.56

Total Images: 367156 98.77 27.55

Javascript: 41608 9.09 1.02

CSS: 21358 4.86 0.71

Multimedia: 0 0.00 0.00

Other: 0 0.00 0.00

 

 

Do you have any clue why my site StylingAgenten.se is so slow? All the underpages are also slow...:(

 

I guess the size of the files above has a part of the problem I have not fins any way yet to reduce them thou...

 

I did follow some tips here and compremized the .js and .css files. I also use Gzip comression.

 

Please help me!

 

Best Regards

Andreas

 

One other thing that I dont understand is that my friend site www.beautysecrets.se, using OScommerce has regarding to http://analyze.websiteoptimization.com a larger amount of image files to download...but it takes much faster time. How is that even possible, is it because of the provider of the server hosting? I use a quite big provider and they say they have fast responstime to their servers.

 

Please help me with this..I dont know what to do :'(

 

Best Regards

Andreas

Link to comment
Share on other sites

One other thing that I dont understand is that my friend site www.beautysecrets.se, using OScommerce has regarding to http://analyze.websiteoptimization.com a larger amount of image files to download...but it takes much faster time. How is that even possible, is it because of the provider of the server hosting? I use a quite big provider and they say they have fast responstime to their servers.

 

Please help me with this..I dont know what to do :'(

 

Best Regards

Andreas

I have checked your page with page speed in Firefox and you would benefit from adding this into .htaccess

# BEGIN Expire headers

 

ExpiresActive On

ExpiresDefault "access plus 1 seconds"

ExpiresByType image/jpeg "access plus 2592000 seconds"

ExpiresByType image/png "access plus 2592000 seconds"

ExpiresByType image/gif "access plus 2592000 seconds"

ExpiresByType image/x-icon "access plus 2592000 seconds"

ExpiresByType text/css "access plus 604800 seconds"

ExpiresByType text/javascript "access plus 604800 seconds"

ExpiresByType application/javascript "access plus 604800 seconds"

ExpiresByType text/html "access plus 2592000 seconds"

 

# END Expire headers

 

Also, a number of your images do not have dimensions specified

The following image(s) are missing width and/or height attributes.

The following image(s) are missing width and/or height attributes.

   * http://b.static.ak.fbcdn.net/rsrc.php/yo/r/UlIqmHJn-SK.gif (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs1327.snc4/161752_685020563_102781_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs175.ash2/41706_754080294_7931574_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs266.snc3/23069_587135004_3063_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs321.snc4/41369_693972233_3377_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs321.snc4/41383_520311783_4241_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs331.snc4/41632_541010705_3399_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs429.ash2/70837_661530374_5092124_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs448.snc4/49308_10617643_3623_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs464.snc4/49006_576099427_1867713_q.jpg (Dimensions: 50 x 50)
   * http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs726.ash1/161822_603946355_1208461_q.jpg (Dimensions: 50 x 50)

 

Placing your snow javascript at the bottom of the page instead of the top would increase page load

Link to comment
Share on other sites

 

Hi!

Thank you SO much for your help, I will try change what you suggest and then reply the progress.

 

Thanx again!!

 

//Andreas

Link to comment
Share on other sites

 

 

Hi again,

 

I just have one question about the addons :) , will it also be able to install in RC2 with the same positive effects as for MS2?

 

Best Regards

Andreas

Link to comment
Share on other sites

Hi again,

 

I just have one question about the addons :) , will it also be able to install in RC2 with the same positive effects as for MS2?

 

Best Regards

Andreas

 

Hi:)

I found another strange thing with the KISS debugging that is shown at my site. One example is in the site below:

 

http://www.stylingagenten.se/hair-styling-conditioner-c-1_15.html

 

There seems to be a lot of duplicated queries, do you know why?

 

Number: 58

Time: 0.0003 Seconds.

Query: select products_description, products_id from products_description where products_id = '146' and language_id = '1'

 

Number: 59

Time: 0.0003 Seconds.

Query: select products_description, products_id from products_description where products_id = '146' and language_id = '1'

 

I really hope you help me with this :)

 

Best Regards

Andreas

Link to comment
Share on other sites

Replace the google tracker with the asynchronous version (replace XXXX with your number)

 

<script type="text/javascript">

var _gaq = _gaq || [];

_gaq.push(['_setAccount', 'UA-1XXXXXXXX-X']);

_gaq.push(['_trackPageview']);

(function() {

var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

})();

</script>

Link to comment
Share on other sites

Replace the google tracker with the asynchronous version (replace XXXX with your number)

 

<script type="text/javascript">

var _gaq = _gaq || [];

_gaq.push(['_setAccount', 'UA-1XXXXXXXX-X']);

_gaq.push(['_trackPageview']);

(function() {

var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

})();

</script>

 

Hi Paul!

Thank you for informing me this. So it is only added a "1" before the key in the asynchronous version? I have the trackingcode installed in footer.php and in checkout_success.php, should I write that number in both files? I'm sorry for my dumb questions:)

 

Btw. do you have any good tip where I can read how to install Analytics correctly? I used an old addon before, but the last months it seems to measure completely wrong.. Thank you for your help!

 

Best Regards

Andreas

Link to comment
Share on other sites

Hi Paul!

Thank you for informing me this. So it is only added a "1" before the key in the asynchronous version? I have the trackingcode installed in footer.php and in checkout_success.php, should I write that number in both files? I'm sorry for my dumb questions:)

 

Btw. do you have any good tip where I can read how to install Analytics correctly? I used an old addon before, but the last months it seems to measure completely wrong.. Thank you for your help!

 

Best Regards

Andreas

 

The 1 should not be there (my error)

<script type="text/javascript">

var _gaq = _gaq || [];

_gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);

_gaq.push(['_trackPageview']);

(function() {

var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

})();

</script>

 

This goes in footer.php. It does not need to go in any other file

Link to comment
Share on other sites

stylesheet.css should be loaded before the xxxx.js files

 

try moving the banner rotator to the footer.php

 

<script type="text/javascript">

$(document).ready(function(){

bannerRotator('#bannerRotator', 500, 4000);

});

</script>

 

Loading javascript initialisation later in the document allows the page to appear on screen with the javascript loading in the background

Link to comment
Share on other sites

The browser of the client is caching the stylesheet. Since it is a static file there is nothing to cache server side.

 

 

Just a thought. If I created a PHP file with the stylesheet information in, would that be parsed and load faster than a .css file? I am just considering this, as the PHP file is parsed server side.

Link to comment
Share on other sites

 

Hi!

I see that I have quite many javascript in the head sections in general, I will try move them down in the end of the body instead and hopefully it will help also.

 

Most of teh addons above is created for MS2, are they still effective for RC2 version of OSCommerce as I use?

 

I hope you had a great new year celebration!!

 

Best Regards

Andreas

Link to comment
Share on other sites

Hi!

I see that I have quite many javascript in the head sections in general, I will try move them down in the end of the body instead and hopefully it will help also.

 

Most of teh addons above is created for MS2, are they still effective for RC2 version of OSCommerce as I use?

 

I hope you had a great new year celebration!!

 

Best Regards

Andreas

I use v2.3.1 and they are still relevant. Do a file compare to ensure that they have not been previously altered. ( I have enable/disable categories and had to alter to suit)

Link to comment
Share on other sites

Just a thought. If I created a PHP file with the stylesheet information in, would that be parsed and load faster than a .css file? I am just considering this, as the PHP file is parsed server side.

 

Do you use like this http://www.csscompressor.com/ ?

:blink:
osCommerce based shop owner with minimal design and focused on background works. When the less is more.
Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store.

Link to comment
Share on other sites

I use v2.3.1 and they are still relevant. Do a file compare to ensure that they have not been previously altered. ( I have enable/disable categories and had to alter to suit)

 

Hi!

I would really appreciate some help to integrate this addon

http://addons.oscommerce.com/info/4083

to my RC2 store.

 

This is how my general.php looks like, i can't get it right :blink:. Because I got RC2 store there need ¨do some alter adjustments from the instructions, as Paul said before.

 

Please help:)

 

<?php
/*
 $Id: general.php 1739 2007-12-20 00:52:16Z hpdl $

 osCommerce, Open Source E-Commerce Solutions
 http://www.oscommerce.com

 Copyright (c) 2007 osCommerce

 Released under the GNU General Public License
*/

////
// Stop from parsing any further PHP code
 function tep_exit() {
  tep_session_close();
  exit();
 }

////
// Redirect to another page or site
 function tep_redirect($url) {
   if ( (strstr($url, "\n") != false) || (strstr($url, "\r") != false) ) { 
     tep_redirect(tep_href_link(FILENAME_DEFAULT, '', 'NONSSL', false));
   }

   if ( (ENABLE_SSL == true) && (getenv('HTTPS') == 'on') ) { // We are loading an SSL page
     if (substr($url, 0, strlen(HTTP_SERVER)) == HTTP_SERVER) { // NONSSL url
       $url = HTTPS_SERVER . substr($url, strlen(HTTP_SERVER)); // Change it to SSL
     }
   }

   header('Location: ' . $url);

   tep_exit();
 }

////
// Parse the data used in the html tags to ensure the tags will not break
 function tep_parse_input_field_data($data, $parse) {
   return strtr(trim($data), $parse);
 }

 function tep_output_string($string, $translate = false, $protected = false) {
   if ($protected == true) {
     return htmlspecialchars($string);
   } else {
     if ($translate == false) {
       return tep_parse_input_field_data($string, array('"' => '"'));
     } else {
       return tep_parse_input_field_data($string, $translate);
     }
   }
 }

 function tep_output_string_protected($string) {
   return tep_output_string($string, false, true);
 }

function tep_sanitize_string($string) {
   $patterns = array ('/ +/','/[<>]/');
$replace = array (' ', '_');
   return preg_replace($patterns, $replace, trim($string));
 }


////
// Return a random row from a database query
 function tep_random_select($query) {
   $random_product = '';
   $random_query = tep_db_query($query);
   $num_rows = tep_db_num_rows($random_query);
   if ($num_rows > 0) {
     $random_row = tep_rand(0, ($num_rows - 1));
     tep_db_data_seek($random_query, $random_row);
     $random_product = tep_db_fetch_array($random_query);
   }

   return $random_product;
 }

////
// Return a product's name
// TABLES: products
 function tep_get_products_name($product_id, $language = '') {
   global $languages_id;

   if (empty($language)) $language = $languages_id;

   $product_query = tep_db_query("select products_name from " . TABLE_PRODUCTS_DESCRIPTION . " where products_id = '" . (int)$product_id . "' and language_id = '" . (int)$language . "'");
   $product = tep_db_fetch_array($product_query);

   return $product['products_name'];
 }

////
// Return a product's special price (returns nothing if there is no offer)
// TABLES: products
 function tep_get_products_special_price($product_id) {
   $product_query = tep_db_query("select specials_new_products_price from " . TABLE_SPECIALS . " where products_id = '" . (int)$product_id . "' and status");
   $product = tep_db_fetch_array($product_query);

   return $product['specials_new_products_price'];
 }

////
// Return a product's stock
// TABLES: products
 function tep_get_products_stock($products_id) {
   $products_id = tep_get_prid($products_id);
   $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . (int)$products_id . "'");
   $stock_values = tep_db_fetch_array($stock_query);

   return $stock_values['products_quantity'];
 }

////
// Check if the required stock is available
// If insufficent stock is available return an out of stock message
 function tep_check_stock($products_id, $products_quantity) {
   $stock_left = tep_get_products_stock($products_id) - $products_quantity;
   $out_of_stock = '';

   if ($stock_left < 0) {
     $out_of_stock = '<span class="markProductOutOfStock">' . STOCK_MARK_PRODUCT_OUT_OF_STOCK . '</span>';
   }

   return $out_of_stock;
 }

////
// Break a word in a string if it is longer than a specified length ($len)
 function tep_break_string($string, $len, $break_char = '-') {
   $l = 0;
   $output = '';
   for ($i=0, $n=strlen($string); $i<$n; $i++) {
     $char = substr($string, $i, 1);
     if ($char != ' ') {
       $l++;
     } else {
       $l = 0;
     }
     if ($l > $len) {
       $l = 1;
       $output .= $break_char;
     }
     $output .= $char;
   }

   return $output;
 }

////
// Return all HTTP GET variables, except those passed as a parameter
 function tep_get_all_get_params($exclude_array = '') {
   global $HTTP_GET_VARS;

   if (!is_array($exclude_array)) $exclude_array = array();

   $get_url = '';
   if (is_array($HTTP_GET_VARS) && (sizeof($HTTP_GET_VARS) > 0)) {
     reset($HTTP_GET_VARS);
     while (list($key, $value) = each($HTTP_GET_VARS)) {
       if ( (strlen($value) > 0) && ($key != tep_session_name()) && ($key != 'error') && (!in_array($key, $exclude_array)) && ($key != 'x') && ($key != 'y') ) {
         $get_url .= $key . '=' . rawurlencode(stripslashes($value)) . '&';
       }
     }
   }

   return $get_url;
 }

////
// Returns an array with countries
// TABLES: countries
 function tep_get_countries($countries_id = '', $with_iso_codes = false) {
   $countries_array = array();
   if (tep_not_null($countries_id)) {
     if ($with_iso_codes == true) {
       $countries = tep_db_query("select countries_name, countries_iso_code_2, countries_iso_code_3 from " . TABLE_COUNTRIES . " where countries_id = '" . (int)$countries_id . "' order by countries_name");
       $countries_values = tep_db_fetch_array($countries);
       $countries_array = array('countries_name' => $countries_values['countries_name'],
                                'countries_iso_code_2' => $countries_values['countries_iso_code_2'],
                                'countries_iso_code_3' => $countries_values['countries_iso_code_3']);
     } else {
       $countries = tep_db_query("select countries_name from " . TABLE_COUNTRIES . " where countries_id = '" . (int)$countries_id . "'");
       $countries_values = tep_db_fetch_array($countries);
       $countries_array = array('countries_name' => $countries_values['countries_name']);
     }
   } else {
     $countries = tep_db_query("select countries_id, countries_name from " . TABLE_COUNTRIES . " order by countries_name");
     while ($countries_values = tep_db_fetch_array($countries)) {
       $countries_array[] = array('countries_id' => $countries_values['countries_id'],
                                  'countries_name' => $countries_values['countries_name']);
     }
   }

   return $countries_array;
 }

////
// Alias function to tep_get_countries, which also returns the countries iso codes
 function tep_get_countries_with_iso_codes($countries_id) {
   return tep_get_countries($countries_id, true);
 }

////
// Generate a path to categories
 function tep_get_path($current_category_id = '') {
   global $cPath_array;

   if (tep_not_null($current_category_id)) {
     $cp_size = sizeof($cPath_array);
     if ($cp_size == 0) {
       $cPath_new = $current_category_id;
     } else {
       $cPath_new = '';
       $last_category_query = tep_db_query("select parent_id from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$cPath_array[($cp_size-1)] . "'");
       $last_category = tep_db_fetch_array($last_category_query);

       $current_category_query = tep_db_query("select parent_id from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$current_category_id . "'");
       $current_category = tep_db_fetch_array($current_category_query);

       if ($last_category['parent_id'] == $current_category['parent_id']) {
         for ($i=0; $i<($cp_size-1); $i++) {
           $cPath_new .= '_' . $cPath_array[$i];
         }
       } else {
         for ($i=0; $i<$cp_size; $i++) {
           $cPath_new .= '_' . $cPath_array[$i];
         }
       }
       $cPath_new .= '_' . $current_category_id;

       if (substr($cPath_new, 0, 1) == '_') {
         $cPath_new = substr($cPath_new, 1);
       }
     }
   } else {
     $cPath_new = implode('_', $cPath_array);
   }

   return 'cPath=' . $cPath_new;
 }

////
// Returns the clients browser
 function tep_browser_detect($component) {
   global $HTTP_USER_AGENT;

   return stristr($HTTP_USER_AGENT, $component);
 }

////
// Alias function to tep_get_countries()
 function tep_get_country_name($country_id) {
   $country_array = tep_get_countries($country_id);

   return $country_array['countries_name'];
 }

////
// Returns the zone (State/Province) name
// TABLES: zones
 function tep_get_zone_name($country_id, $zone_id, $default_zone) {
   $zone_query = tep_db_query("select zone_name from " . TABLE_ZONES . " where zone_country_id = '" . (int)$country_id . "' and zone_id = '" . (int)$zone_id . "'");
   if (tep_db_num_rows($zone_query)) {
     $zone = tep_db_fetch_array($zone_query);
     return $zone['zone_name'];
   } else {
     return $default_zone;
   }
 }

////
// Returns the zone (State/Province) code
// TABLES: zones
 function tep_get_zone_code($country_id, $zone_id, $default_zone) {
   $zone_query = tep_db_query("select zone_code from " . TABLE_ZONES . " where zone_country_id = '" . (int)$country_id . "' and zone_id = '" . (int)$zone_id . "'");
   if (tep_db_num_rows($zone_query)) {
     $zone = tep_db_fetch_array($zone_query);
     return $zone['zone_code'];
   } else {
     return $default_zone;
   }
 }

////
// Wrapper function for round()
 function tep_round($number, $precision) {
   if (strpos($number, '.') && (strlen(substr($number, strpos($number, '.')+1)) > $precision)) {
     $number = substr($number, 0, strpos($number, '.') + 1 + $precision + 1);

     if (substr($number, -1) >= 5) {
       if ($precision > 1) {
         $number = substr($number, 0, -1) + ('0.' . str_repeat(0, $precision-1) . '1');
       } elseif ($precision == 1) {
         $number = substr($number, 0, -1) + 0.1;
       } else {
         $number = substr($number, 0, -1) + 1;
       }
     } else {
       $number = substr($number, 0, -1);
     }
   }

   return $number;
 }

////
// Returns the tax rate for a zone / class
// TABLES: tax_rates, zones_to_geo_zones
 function tep_get_tax_rate($class_id, $country_id = -1, $zone_id = -1) {
   global $customer_zone_id, $customer_country_id;

   if ( ($country_id == -1) && ($zone_id == -1) ) {
     if (!tep_session_is_registered('customer_id')) {
       $country_id = STORE_COUNTRY;
       $zone_id = STORE_ZONE;
     } else {
       $country_id = $customer_country_id;
       $zone_id = $customer_zone_id;
     }
   }

   $tax_query = tep_db_query("select sum(tax_rate) as tax_rate from " . TABLE_TAX_RATES . " tr left join " . TABLE_ZONES_TO_GEO_ZONES . " za on (tr.tax_zone_id = za.geo_zone_id) left join " . TABLE_GEO_ZONES . " tz on (tz.geo_zone_id = tr.tax_zone_id) where (za.zone_country_id is null or za.zone_country_id = '0' or za.zone_country_id = '" . (int)$country_id . "') and (za.zone_id is null or za.zone_id = '0' or za.zone_id = '" . (int)$zone_id . "') and tr.tax_class_id = '" . (int)$class_id . "' group by tr.tax_priority");
   if (tep_db_num_rows($tax_query)) {
     $tax_multiplier = 1.0;
     while ($tax = tep_db_fetch_array($tax_query)) {
       $tax_multiplier *= 1.0 + ($tax['tax_rate'] / 100);
     }
     return ($tax_multiplier - 1.0) * 100;
   } else {
     return 0;
   }
 }

////
// Return the tax description for a zone / class
// TABLES: tax_rates;
 function tep_get_tax_description($class_id, $country_id, $zone_id) {
   $tax_query = tep_db_query("select tax_description from " . TABLE_TAX_RATES . " tr left join " . TABLE_ZONES_TO_GEO_ZONES . " za on (tr.tax_zone_id = za.geo_zone_id) left join " . TABLE_GEO_ZONES . " tz on (tz.geo_zone_id = tr.tax_zone_id) where (za.zone_country_id is null or za.zone_country_id = '0' or za.zone_country_id = '" . (int)$country_id . "') and (za.zone_id is null or za.zone_id = '0' or za.zone_id = '" . (int)$zone_id . "') and tr.tax_class_id = '" . (int)$class_id . "' order by tr.tax_priority");
   if (tep_db_num_rows($tax_query)) {
     $tax_description = '';
     while ($tax = tep_db_fetch_array($tax_query)) {
       $tax_description .= $tax['tax_description'] . ' + ';
     }
     $tax_description = substr($tax_description, 0, -3);

     return $tax_description;
   } else {
     return TEXT_UNKNOWN_TAX_RATE;
   }
 }

////
// Add tax to a products price
 function tep_add_tax($price, $tax) {
   if ( (DISPLAY_PRICE_WITH_TAX == 'true') && ($tax > 0) ) {
     return $price + tep_calculate_tax($price, $tax);
   } else {
     return $price;
   }
 }

// Calculates Tax rounding the result
 function tep_calculate_tax($price, $tax) {
   return $price * $tax / 100;
 }

////
// Return the number of products in a category
// TABLES: products, products_to_categories, categories
function tep_count_products_in_category($category_id, $include_inactive = false) {

   if ($include_inactive) {
       $subindex = 'all';
       $active_clause = '';
   } else {
       $subindex = 'active_only';
       $active_clause = "and p.products_status = '1'";
   }
   if (!isset($GLOBALS['products_in_category'][$subindex])) {
       $query = tep_db_query("
           select   categories_id as category, parent_id,
                    0 as num_products, 0 as total
           from     " . TABLE_CATEGORIES . " c
       ");
       while ($row = tep_db_fetch_array($query)) {
           $GLOBALS['products_in_category'][$subindex][$row['category']] = $row;
       }
       $query = tep_db_query("
           select   count(*) as num_products,
                    p2c.categories_id as category
           from     " . TABLE_PRODUCTS . " p,
                    " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c
           where    p.products_id = p2c.products_id
           $active_clause
           group by category
       ");
       while ($row = tep_db_fetch_array($query)) {
           $GLOBALS['products_in_category'][$subindex][$row['category']]['num_products'] = $row['num_products'];
       }

       foreach ($GLOBALS['products_in_category'][$subindex] as $row) {
           $cat = $row['category'];
           $num = $row['num_products'];
           do {
               if (!isset($GLOBALS['products_in_category'][$subindex][$cat])) {
                   $GLOBALS['products_in_category'][$subindex][$cat] = array();
               }
               $GLOBALS['products_in_category'][$subindex][$cat]['total'] += $num;
               $cat = $GLOBALS['products_in_category'][$subindex][$cat]['parent_id'];
           } while ($cat > 0);
       }
   }
   $pic =& $GLOBALS['products_in_category'][$subindex];

   if (isset($pic[$category_id]) && isset($pic[$category_id]['total'])) {
       return($pic[$category_id]['total']);
   } else {
       return 0;
   }

}

////
// Return true if the category has subcategories
// TABLES: categories
 function tep_has_category_subcategories($category_id) {
   $child_category_query = tep_db_query("select count(*) as count from " . TABLE_CATEGORIES . " where parent_id = '" . (int)$category_id . "'");
   $child_category = tep_db_fetch_array($child_category_query);

   if ($child_category['count'] > 0) {
     return true;
   } else {
     return false;
   }
 }

////
// Returns the address_format_id for the given country
// TABLES: countries;
 function tep_get_address_format_id($country_id) {
   $address_format_query = tep_db_query("select address_format_id as format_id from " . TABLE_COUNTRIES . " where countries_id = '" . (int)$country_id . "'");
   if (tep_db_num_rows($address_format_query)) {
     $address_format = tep_db_fetch_array($address_format_query);
     return $address_format['format_id'];
   } else {
     return '1';
   }
 }

////
// Return a formatted address
// TABLES: address_format
 function tep_address_format($address_format_id, $address, $html, $boln, $eoln) {
   $address_format_query = tep_db_query("select address_format as format from " . TABLE_ADDRESS_FORMAT . " where address_format_id = '" . (int)$address_format_id . "'");
   $address_format = tep_db_fetch_array($address_format_query);

   $company = tep_output_string_protected($address['company']);
   if (isset($address['firstname']) && tep_not_null($address['firstname'])) {
     $firstname = tep_output_string_protected($address['firstname']);
     $lastname = tep_output_string_protected($address['lastname']);
   } elseif (isset($address['name']) && tep_not_null($address['name'])) {
     $firstname = tep_output_string_protected($address['name']);
     $lastname = '';
   } else {
     $firstname = '';
     $lastname = '';
   }
   $street = tep_output_string_protected($address['street_address']);
   $suburb = tep_output_string_protected($address['suburb']);
   $city = tep_output_string_protected($address['city']);
   $state = tep_output_string_protected($address['state']);
   if (isset($address['country_id']) && tep_not_null($address['country_id'])) {
     $country = tep_get_country_name($address['country_id']);

     if (isset($address['zone_id']) && tep_not_null($address['zone_id'])) {
       $state = tep_get_zone_code($address['country_id'], $address['zone_id'], $state);
     }
   } elseif (isset($address['country']) && tep_not_null($address['country'])) {
     $country = tep_output_string_protected($address['country']['title']);
   } else {
     $country = '';
   }
   $postcode = tep_output_string_protected($address['postcode']);
   $zip = $postcode;

   if ($html) {
// HTML Mode
     $HR = '<hr>';
     $hr = '<hr>';
     if ( ($boln == '') && ($eoln == "\n") ) { // Values not specified, use rational defaults
       $CR = '<br>';
       $cr = '<br>';
       $eoln = $cr;
     } else { // Use values supplied
       $CR = $eoln . $boln;
       $cr = $CR;
     }
   } else {
// Text Mode
     $CR = $eoln;
     $cr = $CR;
     $HR = '----------------------------------------';
     $hr = '----------------------------------------';
   }

   $statecomma = '';
   $streets = $street;
   if ($suburb != '') $streets = $street . $cr . $suburb;
   if ($state != '') $statecomma = $state . ', ';

   $fmt = $address_format['format'];
   eval("\$address = \"$fmt\";");

   if ( (ACCOUNT_COMPANY == 'true') && (tep_not_null($company)) ) {
     $address = $company . $cr . $address;
   }

   return $address;
 }

////
// Return a formatted address
// TABLES: customers, address_book
 function tep_address_label($customers_id, $address_id = 1, $html = false, $boln = '', $eoln = "\n") {
   if (is_array($address_id) && !empty($address_id)) {
     return tep_address_format($address_id['address_format_id'], $address_id, $html, $boln, $eoln);
   }

   $address_query = tep_db_query("select entry_firstname as firstname, entry_lastname as lastname, entry_company as company, entry_street_address as street_address, entry_suburb as suburb, entry_city as city, entry_postcode as postcode, entry_state as state, entry_zone_id as zone_id, entry_country_id as country_id from " . TABLE_ADDRESS_BOOK . " where customers_id = '" . (int)$customers_id . "' and address_book_id = '" . (int)$address_id . "'");
   $address = tep_db_fetch_array($address_query);

   $format_id = tep_get_address_format_id($address['country_id']);

   return tep_address_format($format_id, $address, $html, $boln, $eoln);
 }

 function tep_row_number_format($number) {
   if ( ($number < 10) && (substr($number, 0, 1) != '0') ) $number = '0' . $number;

   return $number;
 }

 function tep_get_categories($categories_array = '', $parent_id = '0', $indent = '') {
   global $languages_id;

   if (!is_array($categories_array)) $categories_array = array();

   $categories_query = tep_db_query("select c.categories_id, cd.categories_name from " . TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . " cd where parent_id = '" . (int)$parent_id . "' and c.categories_id = cd.categories_id and cd.language_id = '" . (int)$languages_id . "' order by sort_order, cd.categories_name");
   while ($categories = tep_db_fetch_array($categories_query)) {
     $categories_array[] = array('id' => $categories['categories_id'],
                                 'text' => $indent . $categories['categories_name']);

     if ($categories['categories_id'] != $parent_id) {
       $categories_array = tep_get_categories($categories_array, $categories['categories_id'], $indent . '  ');
     }
   }

   return $categories_array;
 }

 function tep_get_manufacturers($manufacturers_array = '') {
   if (!is_array($manufacturers_array)) $manufacturers_array = array();

   $manufacturers_query = tep_db_query("select manufacturers_id, manufacturers_name from " . TABLE_MANUFACTURERS . " order by manufacturers_name");
   while ($manufacturers = tep_db_fetch_array($manufacturers_query)) {
     $manufacturers_array[] = array('id' => $manufacturers['manufacturers_id'], 'text' => $manufacturers['manufacturers_name']);
   }

   return $manufacturers_array;
 }

////
// Return all subcategory IDs
// TABLES: categories
 function tep_get_subcategories(&$subcategories_array, $parent_id = 0) {
   $subcategories_query = tep_db_query("select categories_id from " . TABLE_CATEGORIES . " where parent_id = '" . (int)$parent_id . "'");
   while ($subcategories = tep_db_fetch_array($subcategories_query)) {
     $subcategories_array[sizeof($subcategories_array)] = $subcategories['categories_id'];
     if ($subcategories['categories_id'] != $parent_id) {
       tep_get_subcategories($subcategories_array, $subcategories['categories_id']);
     }
   }
 }

// Output a raw date string in the selected locale date format
// $raw_date needs to be in this format: YYYY-MM-DD HH:MM:SS
 function tep_date_long($raw_date) {
   if ( ($raw_date == '0000-00-00 00:00:00') || ($raw_date == '') ) return false;

   $year = (int)substr($raw_date, 0, 4);
   $month = (int)substr($raw_date, 5, 2);
   $day = (int)substr($raw_date, 8, 2);
   $hour = (int)substr($raw_date, 11, 2);
   $minute = (int)substr($raw_date, 14, 2);
   $second = (int)substr($raw_date, 17, 2);

   return strftime(DATE_FORMAT_LONG, mktime($hour,$minute,$second,$month,$day,$year));
 }

////
// Output a raw date string in the selected locale date format
// $raw_date needs to be in this format: YYYY-MM-DD HH:MM:SS
// NOTE: Includes a workaround for dates before 01/01/1970 that fail on windows servers
 function tep_date_short($raw_date) {
   if ( ($raw_date == '0000-00-00 00:00:00') || empty($raw_date) ) return false;

   $year = substr($raw_date, 0, 4);
   $month = (int)substr($raw_date, 5, 2);
   $day = (int)substr($raw_date, 8, 2);
   $hour = (int)substr($raw_date, 11, 2);
   $minute = (int)substr($raw_date, 14, 2);
   $second = (int)substr($raw_date, 17, 2);

   if (@date('Y', mktime($hour, $minute, $second, $month, $day, $year)) == $year) {
     return date(DATE_FORMAT, mktime($hour, $minute, $second, $month, $day, $year));
   } else {
     return preg_replace('/2037$/', $year, date(DATE_FORMAT, mktime($hour, $minute, $second, $month, $day, 2037)));

 }
 }

////
// Parse search string into indivual objects
 function tep_parse_search_string($search_str = '', &$objects) {
   $search_str = trim(strtolower($search_str));

// Break up $search_str on whitespace; quoted string will be reconstructed later
   $pieces = preg_split('/[[:space:]]+/', $search_str);


 $objects = array();
   $tmpstring = '';
   $flag = '';

   for ($k=0; $k<count($pieces); $k++) {
     while (substr($pieces[$k], 0, 1) == '(') {
       $objects[] = '(';
       if (strlen($pieces[$k]) > 1) {
         $pieces[$k] = substr($pieces[$k], 1);
       } else {
         $pieces[$k] = '';
       }
     }

     $post_objects = array();

     while (substr($pieces[$k], -1) == ')')  {
       $post_objects[] = ')';
       if (strlen($pieces[$k]) > 1) {
         $pieces[$k] = substr($pieces[$k], 0, -1);
       } else {
         $pieces[$k] = '';
       }
     }

// Check individual words

     if ( (substr($pieces[$k], -1) != '"') && (substr($pieces[$k], 0, 1) != '"') ) {
       $objects[] = trim($pieces[$k]);

       for ($j=0; $j<count($post_objects); $j++) {
         $objects[] = $post_objects[$j];
       }
     } else {
/* This means that the $piece is either the beginning or the end of a string.
  So, we'll slurp up the $pieces and stick them together until we get to the
  end of the string or run out of pieces.
*/

// Add this word to the $tmpstring, starting the $tmpstring
      $tmpstring = trim(preg_replace('/"/', ' ', $pieces[$k]));




// Check for one possible exception to the rule. That there is a single quoted word.
       if (substr($pieces[$k], -1 ) == '"') {
// Turn the flag off for future iterations
         $flag = 'off';

         $objects[] = trim($pieces[$k]);

         for ($j=0; $j<count($post_objects); $j++) {
           $objects[] = $post_objects[$j];
         }

         unset($tmpstring);

// Stop looking for the end of the string and move onto the next word.
         continue;
       }

// Otherwise, turn on the flag to indicate no quotes have been found attached to this word in the string.
       $flag = 'on';

// Move on to the next word
       $k++;

// Keep reading until the end of the string as long as the $flag is on

       while ( ($flag == 'on') && ($k < count($pieces)) ) {
         while (substr($pieces[$k], -1) == ')') {
           $post_objects[] = ')';
           if (strlen($pieces[$k]) > 1) {
             $pieces[$k] = substr($pieces[$k], 0, -1);
           } else {
             $pieces[$k] = '';
           }
         }

// If the word doesn't end in double quotes, append it to the $tmpstring.
         if (substr($pieces[$k], -1) != '"') {
// Tack this word onto the current string entity
           $tmpstring .= ' ' . $pieces[$k];

// Move on to the next word
           $k++;
           continue;
         } else {
/* If the $piece ends in double quotes, strip the double quotes, tack the
  $piece onto the tail of the string, push the $tmpstring onto the $haves,
  kill the $tmpstring, turn the $flag "off", and return.
*/
            $tmpstring .= ' ' . trim(preg_replace('/"/', ' ', $pieces[$k]));




// Push the $tmpstring onto the array of stuff to search for
           $objects[] = trim($tmpstring);

           for ($j=0; $j<count($post_objects); $j++) {
             $objects[] = $post_objects[$j];
           }

           unset($tmpstring);

// Turn off the flag to exit the loop
           $flag = 'off';
         }
       }
     }
   }

// add default logical operators if needed
   $temp = array();
   for($i=0; $i<(count($objects)-1); $i++) {
     $temp[] = $objects[$i];
     if ( ($objects[$i] != 'and') &&
          ($objects[$i] != 'or') &&
          ($objects[$i] != '(') &&
          ($objects[$i+1] != 'and') &&
          ($objects[$i+1] != 'or') &&
          ($objects[$i+1] != ')') ) {
       $temp[] = ADVANCED_SEARCH_DEFAULT_OPERATOR;
     }
   }
   $temp[] = $objects[$i];
   $objects = $temp;

   $keyword_count = 0;
   $operator_count = 0;
   $balance = 0;
   for($i=0; $i<count($objects); $i++) {
     if ($objects[$i] == '(') $balance --;
     if ($objects[$i] == ')') $balance ++;
     if ( ($objects[$i] == 'and') || ($objects[$i] == 'or') ) {
       $operator_count ++;
     } elseif ( ($objects[$i]) && ($objects[$i] != '(') && ($objects[$i] != ')') ) {
       $keyword_count ++;
     }
   }

   if ( ($operator_count < $keyword_count) && ($balance == 0) ) {
     return true;
   } else {
     return false;
   }
 }

////
// Check date
 function tep_checkdate($date_to_check, $format_string, &$date_array) {
   $separator_idx = -1;

   $separators = array('-', ' ', '/', '.');
   $month_abbr = array('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec');
   $no_of_days = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

   $format_string = strtolower($format_string);

   if (strlen($date_to_check) != strlen($format_string)) {
     return false;
   }

   $size = sizeof($separators);
   for ($i=0; $i<$size; $i++) {
     $pos_separator = strpos($date_to_check, $separators[$i]);
     if ($pos_separator != false) {
       $date_separator_idx = $i;
       break;
     }
   }

   for ($i=0; $i<$size; $i++) {
     $pos_separator = strpos($format_string, $separators[$i]);
     if ($pos_separator != false) {
       $format_separator_idx = $i;
       break;
     }
   }

   if ($date_separator_idx != $format_separator_idx) {
     return false;
   }

   if ($date_separator_idx != -1) {
     $format_string_array = explode( $separators[$date_separator_idx], $format_string );
     if (sizeof($format_string_array) != 3) {
       return false;
     }

     $date_to_check_array = explode( $separators[$date_separator_idx], $date_to_check );
     if (sizeof($date_to_check_array) != 3) {
       return false;
     }

     $size = sizeof($format_string_array);
     for ($i=0; $i<$size; $i++) {
       if ($format_string_array[$i] == 'mm' || $format_string_array[$i] == 'mmm') $month = $date_to_check_array[$i];
       if ($format_string_array[$i] == 'dd') $day = $date_to_check_array[$i];
       if ( ($format_string_array[$i] == 'yyyy') || ($format_string_array[$i] == 'aaaa') ) $year = $date_to_check_array[$i];
     }
   } else {
     if (strlen($format_string) == 8 || strlen($format_string) == 9) {
       $pos_month = strpos($format_string, 'mmm');
       if ($pos_month != false) {
         $month = substr( $date_to_check, $pos_month, 3 );
         $size = sizeof($month_abbr);
         for ($i=0; $i<$size; $i++) {
           if ($month == $month_abbr[$i]) {
             $month = $i;
             break;
           }
         }
       } else {
         $month = substr($date_to_check, strpos($format_string, 'mm'), 2);
       }
     } else {
       return false;
     }

     $day = substr($date_to_check, strpos($format_string, 'dd'), 2);
     $year = substr($date_to_check, strpos($format_string, 'yyyy'), 4);
   }

   if (strlen($year) != 4) {
     return false;
   }

   if (!settype($year, 'integer') || !settype($month, 'integer') || !settype($day, 'integer')) {
     return false;
   }

   if ($month > 12 || $month < 1) {
     return false;
   }

   if ($day < 1) {
     return false;
   }

   if (tep_is_leap_year($year)) {
     $no_of_days[1] = 29;
   }

   if ($day > $no_of_days[$month - 1]) {
     return false;
   }

   $date_array = array($year, $month, $day);

   return true;
 }

////
// Check if year is a leap year
 function tep_is_leap_year($year) {
   if ($year % 100 == 0) {
     if ($year % 400 == 0) return true;
   } else {
     if (($year % 4) == 0) return true;
   }

   return false;
 }

////
// Return table heading with sorting capabilities
 function tep_create_sort_heading($sortby, $colnum, $heading) {
   global $PHP_SELF;

   $sort_prefix = '';
   $sort_suffix = '';

   if ($sortby) {
     $sort_prefix = '<a href="' . tep_href_link(basename($PHP_SELF), tep_get_all_get_params(array('page', 'info', 'sort')) . 'page=1&sort=' . $colnum . ($sortby == $colnum . 'a' ? 'd' : 'a')) . '" title="' . tep_output_string(TEXT_SORT_PRODUCTS . ($sortby == $colnum . 'd' || substr($sortby, 0, 1) != $colnum ? TEXT_ASCENDINGLY : TEXT_DESCENDINGLY) . TEXT_BY . $heading) . '" class="productListing-heading">' ;
     $sort_suffix = (substr($sortby, 0, 1) == $colnum ? (substr($sortby, 1, 1) == 'a' ? '+' : '-') : '') . '</a>';
   }

   return $sort_prefix . $heading . $sort_suffix;
 }

////
// Recursively go through the categories and retreive all parent categories IDs
// TABLES: categories
 function tep_get_parent_categories(&$categories, $categories_id) {
   $parent_categories_query = tep_db_query("select parent_id from " . TABLE_CATEGORIES . " where categories_id = '" . (int)$categories_id . "'");
   while ($parent_categories = tep_db_fetch_array($parent_categories_query)) {
     if ($parent_categories['parent_id'] == 0) return true;
     $categories[sizeof($categories)] = $parent_categories['parent_id'];
     if ($parent_categories['parent_id'] != $categories_id) {
       tep_get_parent_categories($categories, $parent_categories['parent_id']);
     }
   }
 }

////
// Construct a category path to the product
// TABLES: products_to_categories
 function tep_get_product_path($products_id) {
   $cPath = '';

   $category_query = tep_db_query("select p2c.categories_id from " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c where p.products_id = '" . (int)$products_id . "' and p.products_status = '1' and p.products_id = p2c.products_id limit 1");
   if (tep_db_num_rows($category_query)) {
     $category = tep_db_fetch_array($category_query);

     $categories = array();
     tep_get_parent_categories($categories, $category['categories_id']);

     $categories = array_reverse($categories);

     $cPath = implode('_', $categories);

     if (tep_not_null($cPath)) $cPath .= '_';
     $cPath .= $category['categories_id'];
   }

   return $cPath;
 }

////
// Return a product ID with attributes
 function tep_get_uprid($prid, $params) {
   if (is_numeric($prid)) {
     $uprid = $prid;

     if (is_array($params) && (sizeof($params) > 0)) {
       $attributes_check = true;
       $attributes_ids = '';

       reset($params);
       while (list($option, $value) = each($params)) {
         if (is_numeric($option) && is_numeric($value)) {
           $attributes_ids .= '{' . (int)$option . '}' . (int)$value;
         } else {
           $attributes_check = false;
           break;
         }
       }

       if ($attributes_check == true) {
         $uprid .= $attributes_ids;
       }
     }
   } else {
     $uprid = tep_get_prid($prid);

     if (is_numeric($uprid)) {
       if (strpos($prid, '{') !== false) {
         $attributes_check = true;
         $attributes_ids = '';

// strpos()+1 to remove up to and including the first { which would create an empty array element in explode()
         $attributes = explode('{', substr($prid, strpos($prid, '{')+1));

         for ($i=0, $n=sizeof($attributes); $i<$n; $i++) {
           $pair = explode('}', $attributes[$i]);

           if (is_numeric($pair[0]) && is_numeric($pair[1])) {
             $attributes_ids .= '{' . (int)$pair[0] . '}' . (int)$pair[1];
           } else {
             $attributes_check = false;
             break;
           }
         }

         if ($attributes_check == true) {
           $uprid .= $attributes_ids;
         }
       }
     } else {
       return false;
     }
   }

   return $uprid;
 }

////
// Return a product ID from a product ID with attributes
 function tep_get_prid($uprid) {
   $pieces = explode('{', $uprid);

   if (is_numeric($pieces[0])) {
     return $pieces[0];
   } else {
     return false;
   }
 }

////
// Return a customer greeting
 function tep_customer_greeting() {
   global $customer_id, $customer_first_name;

   if (tep_session_is_registered('customer_first_name') && tep_session_is_registered('customer_id')) {
     $greeting_string = sprintf(TEXT_GREETING_PERSONAL, tep_output_string_protected($customer_first_name), tep_href_link(FILENAME_PRODUCTS_NEW));
   } else {
     $greeting_string = sprintf(TEXT_GREETING_GUEST, tep_href_link(FILENAME_LOGIN, '', 'SSL'), tep_href_link(FILENAME_CREATE_ACCOUNT, '', 'SSL'));
   }

   return $greeting_string;
 }

////
//! Send email (text/html) using MIME
// This is the central mail function. The SMTP Server should be configured
// correct in php.ini
// Parameters:
// $to_name           The name of the recipient, e.g. "Jan Wildeboer"
// $to_email_address  The eMail address of the recipient,
//                    e.g. [email protected]
// $email_subject     The subject of the eMail
// $email_text        The text of the eMail, may contain HTML entities
// $from_email_name   The name of the sender, e.g. Shop Administration
// $from_email_adress The eMail address of the sender,
//                    e.g. [email protected]

 function tep_mail($to_name, $to_email_address, $email_subject, $email_text, $from_email_name, $from_email_address) {
   if (SEND_EMAILS != 'true') return false;

   // Instantiate a new mail object
   $message = new email(array('X-Mailer: osCommerce Mailer'));

   // Build the text version
   $text = strip_tags($email_text);
   if (EMAIL_USE_HTML == 'true') {
     $message->add_html($email_text, $text);
   } else {
     $message->add_text($text);
   }

   // Send message
   $message->build_message();
   $message->send($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject);
 }

////
// Check if product has attributes
 function tep_has_product_attributes($products_id) {
   $attributes_query = tep_db_query("select count(*) as count from " . TABLE_PRODUCTS_ATTRIBUTES . " where products_id = '" . (int)$products_id . "'");
   $attributes = tep_db_fetch_array($attributes_query);

   if ($attributes['count'] > 0) {
     return true;
   } else {
     return false;
   }
 }

////
// Get the number of times a word/character is present in a string
 function tep_word_count($string, $needle) {
   $temp_array = preg_split('/' . $needle . '/', $string);



   return sizeof($temp_array);
 }

 function tep_count_modules($modules = '') {
   $count = 0;

   if (empty($modules)) return $count;

 $modules_array = explode(';', $modules);


   for ($i=0, $n=sizeof($modules_array); $i<$n; $i++) {
     $class = substr($modules_array[$i], 0, strrpos($modules_array[$i], '.'));

     if (is_object($GLOBALS[$class])) {
       if ($GLOBALS[$class]->enabled) {
         $count++;
       }
     }
   }

   return $count;
 }

 function tep_count_payment_modules() {
   return tep_count_modules(MODULE_PAYMENT_INSTALLED);
 }

 function tep_count_shipping_modules() {
   return tep_count_modules(MODULE_SHIPPING_INSTALLED);
 }

 function tep_create_random_value($length, $type = 'mixed') {
   if ( ($type != 'mixed') && ($type != 'chars') && ($type != 'digits')) return false;

   $rand_value = '';
   while (strlen($rand_value) < $length) {
     if ($type == 'digits') {
       $char = tep_rand(0,9);
     } else {
       $char = chr(tep_rand(0,255));
     }
    if ($type == 'mixed') {
       if (preg_match('/^[a-z0-9]$/i', $char)) $rand_value .= $char;
     } elseif ($type == 'chars') {
       if (preg_match('/^[a-z]$/i', $char)) $rand_value .= $char;
     } elseif ($type == 'digits') {
       if (preg_match('/^[0-9]$/', $char)) $rand_value .= $char;
     }
 }

   return $rand_value;
 }

 function tep_array_to_string($array, $exclude = '', $equals = '=', $separator = '&') {
   if (!is_array($exclude)) $exclude = array();

   $get_string = '';
   if (sizeof($array) > 0) {
     while (list($key, $value) = each($array)) {
       if ( (!in_array($key, $exclude)) && ($key != 'x') && ($key != 'y') ) {
         $get_string .= $key . $equals . $value . $separator;
       }
     }
     $remove_chars = strlen($separator);
     $get_string = substr($get_string, 0, -$remove_chars);
   }

   return $get_string;
 }

 function tep_not_null($value) {
   if (is_array($value)) {
     if (sizeof($value) > 0) {
       return true;
     } else {
       return false;
     }
   } else {
     if (($value != '') && (strtolower($value) != 'null') && (strlen(trim($value)) > 0)) {
       return true;
     } else {
       return false;
     }
   }
 }

////
// Output the tax percentage with optional padded decimals
 function tep_display_tax_value($value, $padding = TAX_DECIMAL_PLACES) {
   if (strpos($value, '.')) {
     $loop = true;
     while ($loop) {
       if (substr($value, -1) == '0') {
         $value = substr($value, 0, -1);
       } else {
         $loop = false;
         if (substr($value, -1) == '.') {
           $value = substr($value, 0, -1);
         }
       }
     }
   }

   if ($padding > 0) {
     if ($decimal_pos = strpos($value, '.')) {
       $decimals = strlen(substr($value, ($decimal_pos+1)));
       for ($i=$decimals; $i<$padding; $i++) {
         $value .= '0';
       }
     } else {
       $value .= '.';
       for ($i=0; $i<$padding; $i++) {
         $value .= '0';
       }
     }
   }

   return $value;
 }

////
// Checks to see if the currency code exists as a currency
// TABLES: currencies
 function tep_currency_exists($code) {
   $code = tep_db_prepare_input($code);

   $currency_query = tep_db_query("select code from " . TABLE_CURRENCIES . " where code = '" . tep_db_input($code) . "' limit 1");
   if (tep_db_num_rows($currency_query)) {
     $currency = tep_db_fetch_array($currency_query);
     return $currency['code'];
   } else {
     return false;
   }
 }

 function tep_string_to_int($string) {
   return (int)$string;
 }

////
// Parse and secure the cPath parameter values
 function tep_parse_category_path($cPath) {
// make sure the category IDs are integers
   $cPath_array = array_map('tep_string_to_int', explode('_', $cPath));

// make sure no duplicate category IDs exist which could lock the server in a loop
   $tmp_array = array();
   $n = sizeof($cPath_array);
   for ($i=0; $i<$n; $i++) {
     if (!in_array($cPath_array[$i], $tmp_array)) {
       $tmp_array[] = $cPath_array[$i];
     }
   }

   return $tmp_array;
 }

////
// Return a random value
 function tep_rand($min = null, $max = null) {
   static $seeded;

   if (!isset($seeded)) {
     mt_srand((double)microtime()*1000000);
     $seeded = true;
   }

   if (isset($min) && isset($max)) {
     if ($min >= $max) {
       return $min;
     } else {
       return mt_rand($min, $max);
     }
   } else {
     return mt_rand();
   }
 }

 function tep_setcookie($name, $value = '', $expire = 0, $path = '/', $domain = '', $secure = 0) {
   setcookie($name, $value, $expire, $path, (tep_not_null($domain) ? $domain : ''), $secure);
 }

 function tep_get_ip_address() {
   global $HTTP_SERVER_VARS;

   if (isset($HTTP_SERVER_VARS)) {
     if (isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'])) {
       $ip = $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'];
     } elseif (isset($HTTP_SERVER_VARS['HTTP_CLIENT_IP'])) {
       $ip = $HTTP_SERVER_VARS['HTTP_CLIENT_IP'];
     } else {
       $ip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
     }
   } else {
     if (getenv('HTTP_X_FORWARDED_FOR')) {
       $ip = getenv('HTTP_X_FORWARDED_FOR');
     } elseif (getenv('HTTP_CLIENT_IP')) {
       $ip = getenv('HTTP_CLIENT_IP');
     } else {
       $ip = getenv('REMOTE_ADDR');
     }
   }

   return $ip;
 }

 function tep_count_customer_orders($id = '', $check_session = true) {
   global $customer_id, $languages_id;

   if (is_numeric($id) == false) {
     if (tep_session_is_registered('customer_id')) {
       $id = $customer_id;
     } else {
       return 0;
     }
   }

   if ($check_session == true) {
     if ( (tep_session_is_registered('customer_id') == false) || ($id != $customer_id) ) {
       return 0;
     }
   }

   $orders_check_query = tep_db_query("select count(*) as total from " . TABLE_ORDERS . " o, " . TABLE_ORDERS_STATUS . " s where o.customers_id = '" . (int)$id . "' and o.orders_status = s.orders_status_id and s.language_id = '" . (int)$languages_id . "' and s.public_flag = '1'");
   $orders_check = tep_db_fetch_array($orders_check_query);

   return $orders_check['total'];
 }

 function tep_count_customer_address_book_entries($id = '', $check_session = true) {
   global $customer_id;

   if (is_numeric($id) == false) {
     if (tep_session_is_registered('customer_id')) {
       $id = $customer_id;
     } else {
       return 0;
     }
   }

   if ($check_session == true) {
     if ( (tep_session_is_registered('customer_id') == false) || ($id != $customer_id) ) {
       return 0;
     }
   }

   $addresses_query = tep_db_query("select count(*) as total from " . TABLE_ADDRESS_BOOK . " where customers_id = '" . (int)$id . "'");
   $addresses = tep_db_fetch_array($addresses_query);

   return $addresses['total'];
 }

// nl2br() prior PHP 4.2.0 did not convert linefeeds on all OSs (it only converted \n)
 function tep_convert_linefeeds($from, $to, $string) {
   if ((PHP_VERSION < "4.0.5") && is_array($from)) {
     return ereg_replace('(' . implode('|', $from) . ')', $to, $string);
   } else {
     return str_replace($from, $to, $string);
   }
 }

 function tep_array_values_to_string($array, $separator = ',') {
$get_string = '';
if (sizeof($array) > 0) {
	while (list($key, $value) = each($array)) {
			$get_string .= $value . $separator;
	}
	$remove_chars = strlen($separator);
	$get_string = substr($get_string, 0, -$remove_chars);
}
return $get_string;
}

?>

 

 

Best Regards Andreas

Link to comment
Share on other sites

This addon is for ADMIN. Your general.php is CATALOG :thumbsup:

 

Hi there Paul!

Now it was easier lol...should not be up and work night time... :blush:

 

Thank you for your assistance:)

 

Best Regards

Andreas

Link to comment
Share on other sites

Hi!

I did most of the tips from you and others here in the forum, I have enhanced my speed with approx. 20%. Thannx for your tips! It is still quite slow, and I found one thing that confuse me a lot.. :huh: that may be a step to the right way. If I compare the page speed with my site, see picture at link

http://www.stylingagenten.se/images/teststyling.jpg

 

with my friend site (he does not host the site himself), see picture at link

http://www.stylingagenten.se/images/testbeauty.jpg

 

My site has has a great download time and size 73,44KB for the first file (as it say) "www.stylingagenten.se"

 

My friend site has a much lower size (28,88KB) for his first file "www.beautysecrets.se"

 

But if you for example look at the total download time and sizes for all the files that is downloaded at www.beautysecrets.se, it has a much greater total size. Also when I check the web page size at some other tools it only measure the first file (73,44KB / 28,88KB)

 

I think my friends site seems much quicker because of that file is much smaller. What is that file, my index.php file is below 30KB how come does it says it is 73,44KB? Does it count procedures in the HEAD tags or something, but not in BODY or do you have any idea how it can differ this much and what I can do to reduce the size?

 

Thankfull for all help! :)

 

Best Regards

Andreas

 

Hi there Paul!

Now it was easier lol...should not be up and work night time... :blush:

 

Thank you for your assistance:)

 

Best Regards

Andreas

Link to comment
Share on other sites

Hi!

I see at http://analyze.websiteoptimization.com/ the html size of my page www.stylingagenten.se is only 11,8K, see picture here:

http://www.stylingagenten.se/images/analyzstyling.jpg

 

and the html size of www.beautysecrets.se is 28K (as the page size mentioned earlier??), see picture here:

http://www.stylingagenten.se/images/analyzbeauty.jpg

 

This make me even more confuse how www.stylingagenten.se seems to have a much greater size as I described in the post above :huh: :) .....

 

Have a great evening/night

 

Best Regards

Andreas

 

Hi!

I did most of the tips from you and others here in the forum, I have enhanced my speed with approx. 20%. Thannx for your tips! It is still quite slow, and I found one thing that confuse me a lot.. :huh: that may be a step to the right way. If I compare the page speed with my site, see picture at link

http://www.stylingagenten.se/images/teststyling.jpg

 

with my friend site (he does not host the site himself), see picture at link

http://www.stylingagenten.se/images/testbeauty.jpg

 

My site has has a great download time and size 73,44KB for the first file (as it say) "www.stylingagenten.se"

 

My friend site has a much lower size (28,88KB) for his first file "www.beautysecrets.se"

 

But if you for example look at the total download time and sizes for all the files that is downloaded at www.beautysecrets.se, it has a much greater total size. Also when I check the web page size at some other tools it only measure the first file (73,44KB / 28,88KB)

 

I think my friends site seems much quicker because of that file is much smaller. What is that file, my index.php file is below 30KB how come does it says it is 73,44KB? Does it count procedures in the HEAD tags or something, but not in BODY or do you have any idea how it can differ this much and what I can do to reduce the size?

 

Thankfull for all help! :)

 

Best Regards

Andreas

Link to comment
Share on other sites

The images highlighted in red are either not there or an incorrect path is showing

 

Hi,

It is strange that is say it is missing, because that picture is shown in the browser. I found one thing that makes the picture seems slow. Its very slow when you click in the menu and hit for example this url:

http://www.stylingagenten.se/hr-styling-c-1.html

 

From what you see it in this picture:

http://www.stylingagenten.se/images/test.jpg

 

There are a lot of "red-missing" pictures, but they are actually existing. It is all the category/product pictures.

 

As you see in the picture they are all beginning download after each picture is done, this takes a long total time. That makes it slow in total. Anyone knows how this is possible to change?

 

Best regards :)

Andreas

Link to comment
Share on other sites

Hi,

It is strange that is say it is missing, because that picture is shown in the browser. I found one thing that makes the picture seems slow. Its very slow when you click in the menu and hit for example this url:

http://www.stylingagenten.se/hr-styling-c-1.html

 

From what you see it in this picture:

http://www.stylingagenten.se/images/test.jpg

 

There are a lot of "red-missing" pictures, but they are actually existing. It is all the category/product pictures.

 

As you see in the picture they are all beginning download after each picture is done, this takes a long total time. That makes it slow in total. Anyone knows how this is possible to change?

 

Best regards :)

Andreas

You have h1 and h2 tags in the head section which should not be there.

 

The 2 images do not exist

    * http://www.stylingagenten.se/images/line_x.gif
   * http://www.stylingagenten.se/images/menu_marker.gif

 

 

You could create a link to your jquery like this instead of serving it. (People will probably already have this cached so a faster load time, plus parallel downloading)

<script type="text/javascript" src="<?php echo (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://') . 'ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'; ?>"></script>
<script type="text/javascript" src="<?php echo (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://') . 'ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js'; ?>"></script>

Link to comment
Share on other sites

Archived

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

×
×
  • Create New...