Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

jQuery/Ajax Advanced Statistics for osCommerce 2.3


Dr. Rolex

Recommended Posts

Advanced Statistics Rev1 for osCommerce 2.3
- Compatible Without mysqlnd -

- Support thread -

 

 

Having made another module for handling products/categories which utilize DataTables, I realized that my store needed a new reporting "engine" to produce statistics/sales data for me so that I don't have to make a new spreadsheet every time I want some statistics.

As of Revision 1 there's still a lot to work on but the the module has come to a point of being useful so I thought I share it with the rest of the osC community as an Add-On.

If you think you have a good idea on new features/stats that could be useful, please share them here on the support forum.

 

DataTables
 

DataTables requests the sales data from your server with Ajax and then builds you a table with a action bar and selectable rows. You can Drag & Drop Column Headers to reorder the table the way you like it. It’s also possible to toggle column visibility.
Clicking on the columns will sort the column ascending/descending.

Clicking on the leftmost plus (+) sign will expand the column to detailed day-by-day per month sales & tax data.

 

Performance
 

The former Reporting Add-On I used was very slow, it queried each row in table orders_products and the amount of queries done to calculate sales & tax for a period was massive!

Data will be loaded from JSON source which also helps improve Performance, especially on slow connections.

 

Make very sure if you are going to use this Add-On that it calculates your data correctly! You have to both double and triple check the reports with another reporting system so you know for sure that everything works.

This is how the Advanced Statistics Add-On calculates your sales data, it’s quite simple:

If you have a tax rate set to 20% and the summary for this tax for 1 day is $200 then it will calculate generated sales with 20% tax this way:

 

[Total Tax] / [Tax Rate] * 100 = Sold Goods with 20% Tax
200             / 20               * 100 = 1000. So Sales 20% will be $1000.

 

As of Rev1, order_totals classes that will be counted are ot_total, ot_tax & ot_shipping.

 

TableTools

 

The TableTools Extension comes with a swf (flash) file which helps e.g. to copy table data to clipboard. Unfortunately, flash is the only way to do this right now..
Copying Data and then Pasting it in your spreadsheet editor is a neat way to quickly create custom reports.
TableTools also comes with buttons to automatically create CSV files. You might need to configure the CSV field separator in advanced_statistics.js. Search for the sFieldSeperator option and set correct separator if you can’t get the CSV to import correctly.

 

Print View

 

Using a CSS with media="print”, a print view is automatically created when you select to print the page. If you have selected to filter orders by status, then there will be an added heading with Status Information, as of Rev1 however, you need to reload the page to get it to display. I’ll fix this later..

You can also use the TableTools ”Print” Button which essentially makes the same thing.

You can also have TableTools create a PDF for you, but it looks like sh*t if you ask me.
Check DataTables homepage on how to configure the layout for this PDF, I will not work on this as I don’t need it (will use CMD/CTRL + P instead..).

 

Note also that some of the themes probably needs some CSS styling fixes if you want to print e.g. background colors of header. Make sure to add these to advanced_statistics_print_view.css.

 

Menus & Navigation

 

I always wanted one of those Slide-In menus so I finally got one; jQuery mmenu. It’s still rather empty, but should fill up with more filtering options and other knobs, buttons & of course whistles soon enough.

To open it; click on the top left icon on the top navigation, it will randomly pick one out of 37 icons on each load but shouldn’t be hard to find as long as you’re not completely ”challenged” by the world around you… :P

There’s a couple of more buttons in the Bootstrap top navigation which will toggle the admin menu and header and also a button to clear all currently applied filters.

To the right on the top navigation you’ll have two dropdowns which will switch theme and filter by orders status.

 

Theming

 

jQuery DataTables comes with some options to implement themes, so I fixed support for five different layouts:

  1. jTable - Looks a bit like the Advanced Order Handler and uses Bootstrap buttons for the seven leftmost buttons.
  2. Original - DataTables as it comes out of the box (more or less)
  3. Bootstrap - Like Original but with the DataTables Bootstrap css & js
  4. jQuery UI - Will adapt to your jQuery-UI Admin Theme (default is Redmond)
  5. jQuery UI Smoothness - Uses Smoothness theme instead of Redmond

Screenshots of all Themes can be found at the bottom of the ReadMe file in the package.

 

Theme-creator

https://www.datatables.net/manual/styling/theme-creator

 

Internationalization

 

Both amCharts and DataTables comes with many language definitions which is included and should automatically load the same language as the one you have set in your admin (assuming the definition exist).

 

amCharts

 

I plan to make a lot of use of amCharts to get easy to interpret charts from store sales etc..
As of Revision 1, you can get a line, area, column, bar, step line, smoothed line, candlestick and OHLC graph for each of the visible columns and for either the specific rows that you have selected (OS style selection, shift/control/CMD click to select multiple rows) or for the entire table(s).

The chart modal is movable (only one move per page load) and also resizable.
Click on the Graph Names at the bottom of the modal to hide/show different line graphs.

 

Security & Compatability

 

All querying with parameters/input variables to your database will be made with MySQLi Prepared Statements. Preferably you should use the MySQL Native Driver (mysqlnd), but I have added support and tested the Add-On without mysqlnd and everything should work.

Prepared Statements removes the threat of MySQL Injections. Not that it matters that much on the admin side of the shop since only authorized users have access, but you can never be too secure, right? ;)

For simple installation I have not messed with more native osC files than necessary and instead included necessary functions in general_functions.php.

If you have any of my previous Add-Ons installed then you might run into a problem under certain conditions when the mysqli_prepared_query and tep_db_fetch_all functions will fail.
If so, then try with replacing the current database functions that you have in ./admin/includes/functions/database.php with the ones that you find in general_functions.php from this Add-on.

 

 

Features for Revision 1

  • Sales/Tax Statistics/Report Generator for osC 2.3.x
  • Only tested on osC 2.3.4 but should work on any version
  • Simple five step Installation - Only three files needs to be modified!
  • Automatically creates HTML table and loads orders from server using AJAX.
  • Export Options: CSV, Copy/Paste, XLS, PDF
  • "Automatic" Print View
  • amCharts Graphs over sales & taxes
  • Very Fast Operation, a shop with 30 000 orders loads in under 2 seconds.
  • jQuery DataTables - https://datatables.net/
  • Drag & Drop Columns
  • Automatic Column Sorting
  • Toggle Column Visibility
  • Detailed day-to-day sales
  • Slide-In Menu with mmenu - http://mmenu.frebsite.nl/
  • Fixed Bootstrap Top Navigation
  • Themes
    1. jTable
    2. Original
    3. Bootstrap
    4. jQuery UI
    5. jQuery UI Smoothness
  • DataTables Internationalization - 63 Language Definitions Included
  • amCharts Internationalization - 29 Language Definitions Included
  • 100% MySQLi Prepared Statements
  • Bootstrap Tooltips
  • Toggleable Visibility of both your store header and Admin menu using CSS3 classes
  • OS style selection, shift/control/CMD click to select multiple rows

 

 

- Plenty of screenshots in package! -

 

Link to comment
Share on other sites

  • Replies 56
  • Created
  • Last Reply

Top Posters In This Topic

Good morning,

 

I have a problem with this add-on, it only shows 1970 

 

Peter

 

Good morning Peter,

 

This is a bit strange, this problem shouldn't happen since date is always stored in the same format in MySQL. But this problem probably has to do with your locale settings and will have an easy fix.

 

Could you post your locale settings in ./admin/includes/languages/[your_language].php

Should be something like this

setlocale(LC_ALL, array('en_US.UTF-8', 'en_US.UTF8', 'enu_usa'));
define('DATE_FORMAT_SHORT', '%m/%d/%Y');  // this is used for strftime()
define('DATE_FORMAT_LONG', '%A %d %B, %Y'); // this is used for strftime()
define('DATE_FORMAT', 'm/d/Y'); // this is used for date()
define('PHP_DATE_TIME_FORMAT', 'm/d/Y H:i:s'); // this is used for date()
Link to comment
Share on other sites

Good morning,

 

I have a problem with this add-on, it only shows 1970 

 

Peter

 

You should also check your PHP error log, if you can see the notice quoted below then the problem might be caused by you having one of my other Add-Ons installed: (you need to set error_reporting to E_ALL in admin/includes/application_top.php to see notices in the log)

 

 

PHP Notice:  Undefined variable: multiQuery

 

If so, then you can solve it this way:

 

 

If you have any of my previous Add-Ons installed then you might run into a problem under certain conditions when the mysqli_prepared_query and tep_db_fetch_all functions will fail.

If so, then try with replacing the current functions that you have in ./admin/includes/functions/database.php with the ones that you find in general_functions.php from this Add-on.

 

The problem can also be attributed to an old version of PHP or perhaps MySQL (most likely PHP).

Link to comment
Share on other sites

My Locale settings :

 

setlocale(LC_TIME, 'en_US.ISO_8859-1');
define('DATE_FORMAT_SHORT', '%m/%d/%Y');  // this is used for strftime()
define('DATE_FORMAT_LONG', '%A %d %B, %Y'); // this is used for strftime()
define('DATE_FORMAT', 'm/d/Y'); // this is used for date()
define('PHP_DATE_TIME_FORMAT', 'm/d/Y H:i:s'); // this is used for date()
define('DATE_TIME_FORMAT', DATE_FORMAT_SHORT . ' %H:%M:%S');
Link to comment
Share on other sites

Hello,

 

 

After installation on 2.3.1, I have this message when I click on "Advanced Statistics" :

 

Fatal error: Call to a member function query() on a non-object in /www/admin/advanced_statistics/general_functions.php on line 47

 

this line is :

"

       $res = $$link->query( $query );

"

 

I don't know why...

 

Thanks.

Link to comment
Share on other sites

 

My Locale settings :

 

setlocale(LC_TIME, 'en_US.ISO_8859-1');
define('DATE_FORMAT_SHORT', '%m/%d/%Y');  // this is used for strftime()
define('DATE_FORMAT_LONG', '%A %d %B, %Y'); // this is used for strftime()
define('DATE_FORMAT', 'm/d/Y'); // this is used for date()
define('PHP_DATE_TIME_FORMAT', 'm/d/Y H:i:s'); // this is used for date()
define('DATE_TIME_FORMAT', DATE_FORMAT_SHORT . ' %H:%M:%S');

 

I've tried :

  1. setlocale(LC_ALL, array('en_US.UTF-8', 'en_US.UTF8', 'enu_usa'));
  2. define('DATE_FORMAT_SHORT', '%m/%d/%Y'); // this is used for strftime()
  3. define('DATE_FORMAT_LONG', '%A %d %B, %Y'); // this is used for strftime()
  4. define('DATE_FORMAT', 'm/d/Y'); // this is used for date()
  5. define('PHP_DATE_TIME_FORMAT', 'm/d/Y H:i:s'); // this is used for date()

 

No solution

 

Error log :

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: Invalid argument supplied for foreach() in /var/www/vhosts/19/176347/admin/advanced_statistics.php on line 38

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in //admin/includes/functions/database.php on line 174

PHP Warning: Invalid argument supplied for foreach() in /var/www/vhosts/19/176347/admin/advanced_statistics.php on line 38

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: end() expects parameter 1 to be array, null given in /admin/advanced_statistics.php on line 185

File does not exist: /admin/ext/tiny_mce/plugins/imagemanager, referer: http://www.espresso-t.nl/admin73pm/advanced_statistics.php

File does not exist: admin/ext/tiny_mce/plugins/filemanager, referer: http://www.espresso-t.nl/admin73pm/advanced_statistics.php

 

Any idea's ?

Edited by pmsmiers
Link to comment
Share on other sites

Hi,

 

Just installed in an almost clean 2.3.4BS store - and firstly I have to say how awesome it looks! Well done

 

But as per the posts above, the reports are restricted to 1970 with the following appearing in my error log:

 

 

PHP Warning:  end() expects parameter 1 to be array, null given in /homeusername/public_html/bootstrap/myadmin/advanced_statistics.php on line 185

Now running on a fully modded, Mobile Friendly 2.3.4 Store with the Excellent MTS installed - See my profile for the mods installed ..... So much thanks for all the help given along the way by forum members.

Link to comment
Share on other sites

OK an update - It would appear that as it was a clean install (with no orders) it was defaulting to 1970.

 

I have added an order to the system and it now displays as it should - ie a sale on todays date of 2015

 

However, the error I mentioned above persists in my error log....

Now running on a fully modded, Mobile Friendly 2.3.4 Store with the Excellent MTS installed - See my profile for the mods installed ..... So much thanks for all the help given along the way by forum members.

Link to comment
Share on other sites

OK another update,

 

As line 185 of the file was looking for an array, as there was only one order it was not finding an array - I have added another order and the error in the error log is now gone :)

 

It looks a very useful system - thank you for your work

Now running on a fully modded, Mobile Friendly 2.3.4 Store with the Excellent MTS installed - See my profile for the mods installed ..... So much thanks for all the help given along the way by forum members.

Link to comment
Share on other sites

Hello,

 

 

After installation on 2.3.1, I have this message when I click on "Advanced Statistics" :

 

Fatal error: Call to a member function query() on a non-object in /www/admin/advanced_statistics/general_functions.php on line 47

 

this line is :

"

       $res = $$link->query( $query );

"

 

I don't know why...

 

Thanks.

 

 

Check your ./admin/includes/functions/database.php, look for

$link = 'db_link'

Make sure if it's 'db_link', if it's something else, then you need to change the same string in ./admin/advanced_statistics/general_functions.php on two places to the one you have in database.php. Change Here:

    function tep_db_fetch_all( $query, $link = 'db_link' ) {

And Here:

    function mysqli_prepared_query( $sql, $typeDef = FALSE, $params = FALSE, $link = "db_link" ) {

This is the only reason I can come up with that produces that error..

Link to comment
Share on other sites

I've tried :

  1. setlocale(LC_ALL, array('en_US.UTF-8', 'en_US.UTF8', 'enu_usa'));
  2. define('DATE_FORMAT_SHORT', '%m/%d/%Y'); // this is used for strftime()
  3. define('DATE_FORMAT_LONG', '%A %d %B, %Y'); // this is used for strftime()
  4. define('DATE_FORMAT', 'm/d/Y'); // this is used for date()
  5. define('PHP_DATE_TIME_FORMAT', 'm/d/Y H:i:s'); // this is used for date()

 

No solution

 

Error log :

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: Invalid argument supplied for foreach() in /var/www/vhosts/19/176347/admin/advanced_statistics.php on line 38

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in //admin/includes/functions/database.php on line 174

PHP Warning: Invalid argument supplied for foreach() in /var/www/vhosts/19/176347/admin/advanced_statistics.php on line 38

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: mysqli_prepare() expects parameter 1 to be mysqli, resource given in /admin/includes/functions/database.php on line 174

PHP Warning: end() expects parameter 1 to be array, null given in /admin/advanced_statistics.php on line 185

File does not exist: /admin/ext/tiny_mce/plugins/imagemanager, referer: http://www.espresso-t.nl/admin73pm/advanced_statistics.php

File does not exist: admin/ext/tiny_mce/plugins/filemanager, referer: http://www.espresso-t.nl/admin73pm/advanced_statistics.php

 

Any idea's ?

 

Did you try my suggestion in post #5?

 

 

Look in your ./admin/includes/functions/database.php for mysqli_prepared_query and tep_db_fetch_all functions. If you can find them, try with commenting them out or removing them to see if it solves your problem.

Link to comment
Share on other sites

OK another update,

 

As line 185 of the file was looking for an array, as there was only one order it was not finding an array - I have added another order and the error in the error log is now gone :)

 

It looks a very useful system - thank you for your work

 

You're welcome!  :thumbsup: 

 

---

 

New features that I have just added is automatic saving of settings to Cookie and localStorage (just like in the Order Handler) and I have also added a custom search filter which can be used to filter statistics for anything from the orders table, e.g. filtering stats for order just from a specific city, from a specific customer, country, etc..

 

I will post updates/new features to the Add-On here rather than uploading a new package each time.

 

I found out that I could clear my old images posted on the forum so now I was able to attach some of the screenshots from the Add-On Package.

 

post-318284-0-76798700-1424298153_thumb.jpg post-318284-0-50043300-1424298246_thumb.jpg post-318284-0-99860800-1424298317_thumb.jpg

Link to comment
Share on other sites

Did you try my suggestion in post #5?

 

 

Look in your ./admin/includes/functions/database.php for mysqli_prepared_query and tep_db_fetch_all functions. If you can find them, try with commenting them out or removing them to see if it solves your problem.

Yes, I only have  mysqli_prepared_query and I tried commenting it out but then my whole admin panel is gone

Link to comment
Share on other sites

Yes, I only have  mysqli_prepared_query and I tried commenting it out but then my whole admin panel is gone

 

Did you get a fatal error in your PHP log when this happened? You probably just forgot to comment a bracket, }, or something.

 

But perhaps it's simpler to just replace the mysqli_prepared_query function in database.php. Replace it with the code below

    function mysqli_prepared_query( $sql, $typeDef = FALSE, $params = FALSE, $link = "db_link" ) {
      global $$link;

      if ( false === $typeDef || empty( $typeDef ) ) {
        return tep_db_fetch_all( $sql );
      }

      # Kiss Error Debugger
      $start_time = microtime( true );

      if ( $stmt = mysqli_prepare( $$link, $sql ) ) {
        if ( count( $params ) == count( $params, 1 ) ) {
          $params = array( $params );
          $multiQuery = FALSE;
        } else {
          $multiQuery = TRUE;
        }

        if ( $typeDef ) {
          $bindParams = array();
          $bindParamsReferences = array();
          $bindParams = array_pad( $bindParams, ( count( $params, 1 )-count( $params ) )/count( $params ), "" );
          foreach ( $bindParams as $key => $value ) {
            $bindParamsReferences[ $key ] = &$bindParams[ $key ];
          }
          array_unshift( $bindParamsReferences, $typeDef );
          $bindParamsMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_param' );
          $bindParamsMethod->invokeArgs( $stmt, $bindParamsReferences );
        }

        $result = array();
        foreach ( $params as $queryKey => $query ) {
          foreach ( $bindParams as $paramKey => $value ) {
            $bindParams[ $paramKey ] = $query[ $paramKey ];
          }
          $queryResult = array();
          if ( mysqli_stmt_execute( $stmt ) ) {
            $resultMetaData = mysqli_stmt_result_metadata( $stmt );
            if ( $resultMetaData ) {
              $stmtRow = array();
              $rowReferences = array();
              while ( $field = mysqli_fetch_field( $resultMetaData ) ) {
                $rowReferences[] = &$stmtRow[ $field->name ];
              }
              mysqli_free_result( $resultMetaData );
              $bindResultMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_result' );
              $bindResultMethod->invokeArgs( $stmt, $rowReferences );
              while ( mysqli_stmt_fetch( $stmt ) ) {
                $row = array();
                foreach ( $stmtRow as $key => $value ) {
                  $row[$key] = $value;
                }
                $queryResult[] = $row;
              }
              mysqli_stmt_free_result( $stmt );
            } else {
              $queryResult[] = mysqli_stmt_affected_rows( $stmt );
            }
          } else {
            $queryResult[] = FALSE;
          }
          $result[ $queryKey ] = $queryResult;
        }
        mysqli_stmt_close( $stmt );
      } else {
        $result = FALSE;
      }

      # Kiss Error Debugger
      if ( class_exists( 'KissER' ) ) {
        $sql = interpolateQuery( $sql, $params[0] );
        KissER::q( round( ( microtime( true ) - $start_time ), 4 ), $sql );
      }

      if ( $multiQuery ) {
        return $result;
      } else {
        return $result[0];
      }
    }
Link to comment
Share on other sites

Check your ./admin/includes/functions/database.php, look for

$link = 'db_link'
Make sure if it's 'db_link', if it's something else, then you need to change the same string in ./admin/advanced_statistics/general_functions.php on two places to the one you have in database.php. Change Here:

    function tep_db_fetch_all( $query, $link = 'db_link' ) {
And Here:

    function mysqli_prepared_query( $sql, $typeDef = FALSE, $params = FALSE, $link = "db_link" ) {
This is the only reason I can come up with that produces that error..

 

 

-------------------------------------------------------------------------------------

Hello,

 

It seems I have always $link = 'db_link' in my database.php :

<?php
/*
  $Id$

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

  Copyright (c) 2007 osCommerce

  Released under the GNU General Public License
*/

  function tep_db_connect($server = DB_SERVER, $username = DB_SERVER_USERNAME, $password = DB_SERVER_PASSWORD, $database = DB_DATABASE, $link = 'db_link') {
    global $$link;

    if (USE_PCONNECT == 'true') {
      $$link = mysql_pconnect($server, $username, $password);
    } else {
      $$link = mysql_connect($server, $username, $password);
    }

    if ($$link) mysql_select_db($database);

    return $$link;
  }

  function tep_db_close($link = 'db_link') {
    global $$link;

    return mysql_close($$link);
  }

  function tep_db_error($query, $errno, $error) { 
    die('<font color="#000000"><strong>' . $errno . ' - ' . $error . '<br /><br />' . $query . '<br /><br /><small><font color="#ff0000">[TEP STOP]</font></small><br /><br /></strong></font>');
  }

  function tep_db_query($query, $link = 'db_link') {
    global $$link, $logger;

    if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
      if (!is_object($logger)) $logger = new logger;
      $logger->write($query, 'QUERY');
    }

    $result = mysql_query($query, $$link) or tep_db_error($query, mysql_errno(), mysql_error());

    if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
      if (mysql_error()) $logger->write(mysql_error(), 'ERROR');
    }

    return $result;
  }

  function tep_db_perform($table, $data, $action = 'insert', $parameters = '', $link = 'db_link') {
    reset($data);
    if ($action == 'insert') {
      $query = 'insert into ' . $table . ' (';
      while (list($columns, ) = each($data)) {
        $query .= $columns . ', ';
      }
      $query = substr($query, 0, -2) . ') values (';
      reset($data);
      while (list(, $value) = each($data)) {
        switch ((string)$value) {
          case 'now()':
            $query .= 'now(), ';
            break;
          case 'null':
            $query .= 'null, ';
            break;
          default:
            $query .= '\'' . tep_db_input($value) . '\', ';
            break;
        }
      }
      $query = substr($query, 0, -2) . ')';
    } elseif ($action == 'update') {
      $query = 'update ' . $table . ' set ';
      while (list($columns, $value) = each($data)) {
        switch ((string)$value) {
          case 'now()':
            $query .= $columns . ' = now(), ';
            break;
          case 'null':
            $query .= $columns .= ' = null, ';
            break;
          default:
            $query .= $columns . ' = \'' . tep_db_input($value) . '\', ';
            break;
        }
      }
      $query = substr($query, 0, -2) . ' where ' . $parameters;
    }

    return tep_db_query($query, $link);
  }

  function tep_db_fetch_array($db_query) {
    return mysql_fetch_array($db_query, MYSQL_ASSOC);
  }

  function tep_db_result($result, $row, $field = '') {
    return mysql_result($result, $row, $field);
  }

  function tep_db_num_rows($db_query) {
    return mysql_num_rows($db_query);
  }

  function tep_db_data_seek($db_query, $row_number) {
    return mysql_data_seek($db_query, $row_number);
  }

  function tep_db_insert_id($link = 'db_link') {
    global $$link;

    return mysql_insert_id($$link);
  }

  function tep_db_free_result($db_query) {
    return mysql_free_result($db_query);
  }

  function tep_db_fetch_fields($db_query) {
    return mysql_fetch_field($db_query);
  }

  function tep_db_output($string) {
    return htmlspecialchars($string);
  }

  function tep_db_input($string, $link = 'db_link') {
    global $$link;

    if (function_exists('mysql_real_escape_string')) {
      return mysql_real_escape_string($string, $$link);
    } elseif (function_exists('mysql_escape_string')) {
      return mysql_escape_string($string);
    }

    return addslashes($string);
  }

  function tep_db_prepare_input($string) {
    if (is_string($string)) {
      return trim(stripslashes($string));
    } elseif (is_array($string)) {
      reset($string);
      while (list($key, $value) = each($string)) {
        $string[$key] = tep_db_prepare_input($value);
      }
      return $string;
    } else {
      return $string;
    }
  }
?>

And general_functions.php : (the original)

<?php
/*
  Advanced Statistics Rev1 for osCommerce 2.3.3
  Copyright (C) 2015  Jonas [email protected]

  This file is part of Advanced Statistics Rev1.

  Advanced Statistics Rev1 is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Advanced Statistics Rev1 is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Advanced Statistics Rev1.  If not, see <http://www.gnu.org/licenses/>.
*/

  if ( ! function_exists( 'tep_static_link' ) ) {
    ////
    // The HTML href link with Static Content
    function tep_static_link( $script, $type, $catalog = false, $cookieless = '', $version = null, $connection = 'SSL', $extra = '' ) {

      if ( $catalog == true )
        $script = tep_catalog_href_link( $script, ( is_numeric( $version ) ? $version : '' ), $connection );
      else
        $script = ( ( $cookieless == true ) ? HTTP_COOKIELESS_DOMAIN : '' ) . $script;
      if ( $type == 'script' )
        return '<script src="' . ( ( $cookieless == true ) ? HTTP_COOKIELESS_DOMAIN : '' ) . $script . '" '. $extra . '></script>';

      if ( $type == 'link' )
        return '<link rel="stylesheet" type="text/css" href="' . ( ( $cookieless == true ) ? HTTP_COOKIELESS_DOMAIN : '' ) . $script . '"  '. $extra . ' />';

      return "No link found";
    }
  }


  if ( ! function_exists( 'tep_db_fetch_all' ) ) {

    function tep_db_fetch_all( $query, $link = 'db_link' ) {
        global $$link;

        $res = $$link->query( $query );

        if ( false === $res ) {
          return tep_db_error( $query, mysqli_errno( $$link ), mysqli_error( $$link ) );
        } else {
          if ( true === function_exists( 'mysqli_fetch_all' ) ) {
            $rows = $res->fetch_all(MYSQLI_ASSOC);
          } else {
            while( $row = $res->fetch_array() ) {
              $rows[] = $row;
            }
          }
          $res->close();
          return $rows;
        }
      }

  }

  if ( ! function_exists( 'mysqli_prepared_query' ) ) {

    function mysqli_prepared_query( $sql, $typeDef = FALSE, $params = FALSE, $link = "db_link" ) {
      global $$link;

      if ( false === $typeDef || empty( $typeDef ) ) {
        return tep_db_fetch_all( $sql );
      }

      # Kiss Error Debugger
      $start_time = microtime( true );

      if ( $stmt = mysqli_prepare( $$link, $sql ) ) {
        if ( count( $params ) == count( $params, 1 ) ) {
          $params = array( $params );
          $multiQuery = FALSE;
        } else {
          $multiQuery = TRUE;
        }

        if ( $typeDef ) {
          $bindParams = array();
          $bindParamsReferences = array();
          $bindParams = array_pad( $bindParams, ( count( $params, 1 )-count( $params ) )/count( $params ), "" );
          foreach ( $bindParams as $key => $value ) {
            $bindParamsReferences[ $key ] = &$bindParams[ $key ];
          }
          array_unshift( $bindParamsReferences, $typeDef );
          $bindParamsMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_param' );
          $bindParamsMethod->invokeArgs( $stmt, $bindParamsReferences );
        }

        $result = array();
        foreach ( $params as $queryKey => $query ) {
          foreach ( $bindParams as $paramKey => $value ) {
            $bindParams[ $paramKey ] = $query[ $paramKey ];
          }
          $queryResult = array();
          if ( mysqli_stmt_execute( $stmt ) ) {
            $resultMetaData = mysqli_stmt_result_metadata( $stmt );
            if ( $resultMetaData ) {
              $stmtRow = array();
              $rowReferences = array();
              while ( $field = mysqli_fetch_field( $resultMetaData ) ) {
                $rowReferences[] = &$stmtRow[ $field->name ];
              }
              mysqli_free_result( $resultMetaData );
              $bindResultMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_result' );
              $bindResultMethod->invokeArgs( $stmt, $rowReferences );
              while ( mysqli_stmt_fetch( $stmt ) ) {
                $row = array();
                foreach ( $stmtRow as $key => $value ) {
                  $row[$key] = $value;
                }
                $queryResult[] = $row;
              }
              mysqli_stmt_free_result( $stmt );
            } else {
              $queryResult[] = mysqli_stmt_affected_rows( $stmt );
            }
          } else {
            $queryResult[] = FALSE;
          }
          $result[ $queryKey ] = $queryResult;
        }
        mysqli_stmt_close( $stmt );
      } else {
        $result = FALSE;
      }

      # Kiss Error Debugger
      if ( class_exists( 'KissER' ) ) {
        $sql = interpolateQuery( $sql, $params[0] );
        KissER::q( round( ( microtime( true ) - $start_time ), 4 ), $sql );
      }

      if ( $multiQuery ) {
        return $result;
      } else {
        return $result[0];
      }
    }

  }


  function getMonthArray( $start_date, $end_date, $reverse = true ) {
    $start_timestamp = strtotime( str_replace( '-', '/', $start_date ) );
    $end_timestamp = strtotime( str_replace( '-', '/', $end_date ) );

    $start_month_timestamp = strtotime( date( 'F Y', $start_timestamp ) );
    $current_month_timestamp = strtotime( date( 'F Y', $start_timestamp ) );

    $arr_month = array();

    while ( $current_month_timestamp >= $start_month_timestamp ) {
      $arr_month[ date( 'Y-m', $end_timestamp ) ] = array(
        'year' => date( 'Y', $end_timestamp ),
        'month' => date( 'm', $end_timestamp ),
        'day'   => date( 'd', $end_timestamp ),
        'total' => 0,
      );

      $end_timestamp = strtotime( '-1 month', $end_timestamp );

      $current_month_timestamp = strtotime( date( 'F Y', $end_timestamp ) );
    }

    if ( true === $reverse )
      $arr_month = array_reverse( $arr_month );

    return $arr_month;
  }


  function getDayArray( $start_date, $end_date, $reverse = true ) {
    $start_timestamp = strtotime( $start_date );
    $end_timestamp = strtotime( $end_date );

    $start_month_timestamp = strtotime( date( 'Y-m-d', $start_timestamp ) );
    $current_month_timestamp = strtotime( date( 'Y-m-d', $start_timestamp ) );

    $arr_month = array();

    while ( $current_month_timestamp >= $start_month_timestamp ) {
      $arr_month[ date( 'Y-m-d', $end_timestamp ) ] = array(
        'year' => date( 'Y', $end_timestamp ),
        'month' => date( 'm', $end_timestamp ),
        'day'   => date( 'd', $end_timestamp ),
        'total' => 0,
      );

      $end_timestamp = strtotime( '-1 day', $end_timestamp );

      $current_month_timestamp = strtotime( date( 'Y-m-d', $end_timestamp ) );
    }

    if ( true === $reverse )
      $arr_month = array_reverse( $arr_month );

    array_pop( $arr_month );

    return $arr_month;
  }


  function tep_not_empty( $string ) {
    if ( !isset( $string ) || empty( $string ) ) return false;
    return true;
  }


  function validateDate( $date ) {
    $d = DateTime::createFromFormat( 'Y-m-d', $date );
    return $d && $d->format( 'Y-m-d' ) == $date;
  }


  function tep_preload_scripts() {
    echo tep_static_link( 'advanced_statistics/css/font-awesome.4.3.0.min.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/bootstrap-3.2.0.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/bootstrap-theme-3.2.0.css', 'link', false, false, '0928' );


    // jQuery DataTables 1.10.6-dev 
    echo tep_static_link( 'advanced_statistics/js/jquery.dataTables.min.js', 'script', false, false, '0928' );


    // Plugins
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.colVis.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.tableTools-2.2.4-dev.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.colReorder.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.autoFill.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.keyTable.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.fixedColumns.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/plugins/dataTables.fixedHeader.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/mmenu/js/jquery.mmenu.min.all.js', 'script', false, false, '0928' );


    // jQuery DataTables 1.10.6-dev 
    echo tep_static_link( 'advanced_statistics/css/jquery.dataTables.min.css', 'link', false, false, '0928' );


    // Optional - jQuery UI Integration
    if ( "jqueryui_smooth" == $_GET['theme_selector'] )
      echo tep_static_link( 'advanced_statistics/css/jquery-ui-smoothness-1.11.2.css', 'link', false, false, '0928' );

    if ( "jqueryui_smooth" == $_GET['theme_selector'] || "jqueryui" == $_GET['theme_selector'] ) {
      echo tep_static_link( 'advanced_statistics/css/themes/dataTables.jqueryui.css', 'link', false, false, '0928' );
      echo tep_static_link( 'advanced_statistics/css/themes/dataTables.colvis.jqueryui.css', 'link', false, false, '0928' );
      echo tep_static_link( 'advanced_statistics/css/themes/jquery.dataTables_themeroller-1.10.6-dev.css', 'link', false, false, '0928' );
      echo tep_static_link( 'advanced_statistics/js/themes/dataTables.jqueryui.js', 'script', false, false, '0928' );
    }

    // Optional - Bootstrap Integration
    if ( "bootstrap" == $_GET['theme_selector'] || "jTable" == $_GET['theme_selector'] ) {
      echo tep_static_link( 'advanced_statistics/css/themes/dataTables.bootstrap.css', 'link', false, false, '0928' );
      echo tep_static_link( 'advanced_statistics/js/themes/dataTables.bootstrap.js', 'script', false, false, '0928' );
    }

    // Optional - Custom Theme
    if ( "jTable" == $_GET['theme_selector'] || ! isset( $_GET['theme_selector'] ) )
      echo tep_static_link( 'advanced_statistics/css/themes/dataTables.custom-theme.css', 'link', false, false, '0928' );


    echo tep_static_link( 'advanced_statistics/mmenu/css/jquery.mmenu.all.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/plugins/dataTables.colVis.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/plugins/dataTables.tableTools-2.2.4-dev.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/plugins/dataTables.colReorder.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/plugins/dataTables.autoFill.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/plugins/dataTables.keyTable.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/plugins/dataTables.fontAwesome.css', 'link', false, false, '0928' );

    // Optional - jQuery UI Integration
    // echo tep_static_link( 'advanced_statistics/js/themes/dataTables.jqueryui.js', 'script', false, false, '0928' );

    // Optional - Bootstrap Integration
    // echo tep_static_link( 'advanced_statistics/js/themes/dataTables.bootstrap.js', 'script', false, false, '0928' );


    echo tep_static_link( 'advanced_statistics/css/advanced_statistics.css', 'link', false, false, '0928' );

    // Print View CSS
    echo tep_static_link( 'advanced_statistics/css/advanced_statistics_print_view.css', 'link', false, false, '0928', 'SSL', 'media="print"' );

  }


  function tep_afterload_scripts( $language_code ) {
    //echo tep_static_link( 'advanced_statistics/css/bootstrap-multiselect-3.1.1.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/css/select2-3.5.1.css', 'link', false, false, '0928' );
    //echo tep_static_link( 'advanced_statistics/css/daterangepicker-bs3.css', 'link', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/bootstrap-3.2.0.js', 'script', false, false, '0928' );
    //echo tep_static_link( 'advanced_statistics/js/bootstrap-multiselect-3.1.1.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/select2-3.5.1.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/js/advanced_statistics.js', 'script', false, false, '0928' );

    //echo tep_static_link( 'advanced_statistics/js/jquery-impromptu.js', 'script', false, false, '0928' );
    //echo tep_static_link( 'advanced_statistics/js/jquery.cookie.js', 'script', false, false, '0928' );
    //echo tep_static_link( 'advanced_statistics/js/jquery.ajaxLoader.js', 'script', false, false, '0928' );

    echo tep_static_link( 'advanced_statistics/amcharts/amcharts.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/amcharts/serial.js', 'script', false, false, '0928' );
    echo tep_static_link( 'advanced_statistics/amcharts/themes/none.js', 'script', false, false, '0928' );
    if ( file_exists( 'advanced_statistics/amcharts/lang/' . $language_code . '.js' ) )
      echo tep_static_link( 'advanced_statistics/amcharts/lang/' . $language_code . '.js', 'script', false, false, '0928' );

    //echo tep_static_link( 'advanced_statistics/js/moment.js', 'script', false, false, '0928' );
    //echo tep_static_link( 'advanced_statistics/js/daterangepicker.js', 'script', false, false, '0928' );
  }

Link to comment
Share on other sites

 

-------------------------------------------------------------------------------------

Hello,

 

It seems I have always $link = 'db_link' in my database.php :

 

....

 

 

What version of osCommerce are you using? Your database.php file is really old.

This Add-On was made for osCommerce 2.3 and I think that you're using an older version?

 

You can try with replacing your database.php with the new file from 2.3.4

<?php
/*
  $Id$

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

  Copyright (c) 2013 osCommerce

  Released under the GNU General Public License
*/

  function tep_db_connect($server = DB_SERVER, $username = DB_SERVER_USERNAME, $password = DB_SERVER_PASSWORD, $database = DB_DATABASE, $link = 'db_link') {
    global $$link;

    if (USE_PCONNECT == 'true') {
      $server = 'p:' . $server;
    }

    $$link = mysqli_connect($server, $username, $password, $database);

    if ( !mysqli_connect_errno() ) {
      mysqli_set_charset($$link, 'utf8');
    } 

    return $$link;
  }

  function tep_db_close($link = 'db_link') {
    global $$link;

    return mysqli_close($$link);
  }

  function tep_db_error($query, $errno, $error) {
    global $logger;

    if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
      $logger->write('[' . $errno . '] ' . $error, 'ERROR');
    }

    die('<font color="#000000"><strong>' . $errno . ' - ' . $error . '<br /><br />' . $query . '<br /><br /><small><font color="#ff0000">[TEP STOP]</font></small><br /><br /></strong></font>');
  }

  function tep_db_query($query, $link = 'db_link') {
    global $$link, $logger;

    if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
      if (!is_object($logger)) $logger = new logger;
      $logger->write($query, 'QUERY');
    }

    $result = mysqli_query($$link, $query) or tep_db_error($query, mysqli_errno($$link), mysqli_error($$link));

    return $result;
  }

  function tep_db_perform($table, $data, $action = 'insert', $parameters = '', $link = 'db_link') {
    reset($data);
    if ($action == 'insert') {
      $query = 'insert into ' . $table . ' (';
      while (list($columns, ) = each($data)) {
        $query .= $columns . ', ';
      }
      $query = substr($query, 0, -2) . ') values (';
      reset($data);
      while (list(, $value) = each($data)) {
        switch ((string)$value) {
          case 'now()':
            $query .= 'now(), ';
            break;
          case 'null':
            $query .= 'null, ';
            break;
          default:
            $query .= '\'' . tep_db_input($value) . '\', ';
            break;
        }
      }
      $query = substr($query, 0, -2) . ')';
    } elseif ($action == 'update') {
      $query = 'update ' . $table . ' set ';
      while (list($columns, $value) = each($data)) {
        switch ((string)$value) {
          case 'now()':
            $query .= $columns . ' = now(), ';
            break;
          case 'null':
            $query .= $columns .= ' = null, ';
            break;
          default:
            $query .= $columns . ' = \'' . tep_db_input($value) . '\', ';
            break;
        }
      }
      $query = substr($query, 0, -2) . ' where ' . $parameters;
    }

    return tep_db_query($query, $link);
  }

  function tep_db_fetch_array($db_query) {
    return mysqli_fetch_array($db_query, MYSQLI_ASSOC);
  }

  function tep_db_result($result, $row, $field = '') {
    if ( $field === '' ) {
      $field = 0;
    }

    tep_db_data_seek($result, $row);
    $data = tep_db_fetch_array($result);

    return $data[$field];
  }

  function tep_db_num_rows($db_query) {
    return mysqli_num_rows($db_query);
  }

  function tep_db_data_seek($db_query, $row_number) {
    return mysqli_data_seek($db_query, $row_number);
  }

  function tep_db_insert_id($link = 'db_link') {
    global $$link;

    return mysqli_insert_id($$link);
  }

  function tep_db_free_result($db_query) {
    return mysqli_free_result($db_query);
  }

  function tep_db_fetch_fields($db_query) {
    return mysqli_fetch_field($db_query);
  }

  function tep_db_output($string) {
    return htmlspecialchars($string);
  }

  function tep_db_input($string, $link = 'db_link') {
    global $$link;

    return mysqli_real_escape_string($$link, $string);
  }

  function tep_db_prepare_input($string) {
    if (is_string($string)) {
      return trim(stripslashes($string));
    } elseif (is_array($string)) {
      reset($string);
      while (list($key, $value) = each($string)) {
        $string[$key] = tep_db_prepare_input($value);
      }
      return $string;
    } else {
      return $string;
    }
  }

  function tep_db_affected_rows($link = 'db_link') {
    global $$link;

    return mysqli_affected_rows($$link);
  }

  function tep_db_get_server_info($link = 'db_link') {
    global $$link;

    return mysqli_get_server_info($$link);
  }

  if ( !function_exists('mysqli_connect') ) {
    define('MYSQLI_ASSOC', MYSQL_ASSOC);

    function mysqli_connect($server, $username, $password, $database) {
      if ( substr($server, 0, 2) == 'p:' ) {
        $link = mysql_pconnect(substr($server, 2), $username, $password);
      } else {
        $link = mysql_connect($server, $username, $password);
      }

      if ( $link ) {
        mysql_select_db($database, $link);
      }

      return $link;
    }

    function mysqli_connect_errno($link = null) {
      if ( is_null($link) ) {
        return mysql_errno();
      }

      return mysql_errno($link);
    }

    function mysqli_connect_error($link = null) {
      if ( is_null($link) ) {
        return mysql_error();
      }

      return mysql_error($link);
    }

    function mysqli_set_charset($link, $charset) {
      if ( function_exists('mysql_set_charset') ) {
        return mysql_set_charset($charset, $link);
      }
    }

    function mysqli_close($link) {
      return mysql_close($link);
    }

    function mysqli_query($link, $query) {
      return mysql_query($query, $link);
    }

    function mysqli_errno($link = null) {
      if ( is_null($link) ) {
        return mysql_errno();
      }

      return mysql_errno($link);
    }

    function mysqli_error($link = null) {
      if ( is_null($link) ) {
        return mysql_error();
      }

      return mysql_error($link);
    }

    function mysqli_fetch_array($query, $type) {
      return mysql_fetch_array($query, $type);
    }

    function mysqli_num_rows($query) {
      return mysql_num_rows($query);
    }

    function mysqli_data_seek($query, $offset) {
      return mysql_data_seek($query, $offset);
    }

    function mysqli_insert_id($link) {
      return mysql_insert_id($link);
    }

    function mysqli_free_result($query) {
      return mysql_free_result($query);
    }

    function mysqli_fetch_field($query) {
      return mysql_fetch_field($query);
    }

    function mysqli_real_escape_string($link, $string) {
      if ( function_exists('mysql_real_escape_string') ) {
        return mysql_real_escape_string($string, $link);
      } elseif ( function_exists('mysql_escape_string') ) {
        return mysql_escape_string($string);
      }

      return addslashes($string);
    }

    function mysqli_affected_rows($link) {
      return mysql_affected_rows($link);
    }

    function mysqli_get_server_info($link) {
      return mysql_get_server_info($link);
    }
  }
?>

Link to comment
Share on other sites

 

What version of osCommerce are you using? Your database.php file is really old.

This Add-On was made for osCommerce 2.3 and I think that you're using an older version?

 

You can try with replacing your database.php with the new file from 2.3.4

<?php
/*
  $Id$

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

  Copyright (c) 2013 osCommerce

  Released under the GNU General Public License
*/

  function tep_db_connect($server = DB_SERVER, $username = DB_SERVER_USERNAME, $password = DB_SERVER_PASSWORD, $database = DB_DATABASE, $link = 'db_link') {
    global $$link;

    if (USE_PCONNECT == 'true') {
      $server = 'p:' . $server;
    }

    $$link = mysqli_connect($server, $username, $password, $database);

    if ( !mysqli_connect_errno() ) {
      mysqli_set_charset($$link, 'utf8');
    } 

    return $$link;
  }

  function tep_db_close($link = 'db_link') {
    global $$link;

    return mysqli_close($$link);
  }

  function tep_db_error($query, $errno, $error) {
    global $logger;

    if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
      $logger->write('[' . $errno . '] ' . $error, 'ERROR');
    }

    die('<font color="#000000"><strong>' . $errno . ' - ' . $error . '<br /><br />' . $query . '<br /><br /><small><font color="#ff0000">[TEP STOP]</font></small><br /><br /></strong></font>');
  }

  function tep_db_query($query, $link = 'db_link') {
    global $$link, $logger;

    if (defined('STORE_DB_TRANSACTIONS') && (STORE_DB_TRANSACTIONS == 'true')) {
      if (!is_object($logger)) $logger = new logger;
      $logger->write($query, 'QUERY');
    }

    $result = mysqli_query($$link, $query) or tep_db_error($query, mysqli_errno($$link), mysqli_error($$link));

    return $result;
  }

  function tep_db_perform($table, $data, $action = 'insert', $parameters = '', $link = 'db_link') {
    reset($data);
    if ($action == 'insert') {
      $query = 'insert into ' . $table . ' (';
      while (list($columns, ) = each($data)) {
        $query .= $columns . ', ';
      }
      $query = substr($query, 0, -2) . ') values (';
      reset($data);
      while (list(, $value) = each($data)) {
        switch ((string)$value) {
          case 'now()':
            $query .= 'now(), ';
            break;
          case 'null':
            $query .= 'null, ';
            break;
          default:
            $query .= '\'' . tep_db_input($value) . '\', ';
            break;
        }
      }
      $query = substr($query, 0, -2) . ')';
    } elseif ($action == 'update') {
      $query = 'update ' . $table . ' set ';
      while (list($columns, $value) = each($data)) {
        switch ((string)$value) {
          case 'now()':
            $query .= $columns . ' = now(), ';
            break;
          case 'null':
            $query .= $columns .= ' = null, ';
            break;
          default:
            $query .= $columns . ' = \'' . tep_db_input($value) . '\', ';
            break;
        }
      }
      $query = substr($query, 0, -2) . ' where ' . $parameters;
    }

    return tep_db_query($query, $link);
  }

  function tep_db_fetch_array($db_query) {
    return mysqli_fetch_array($db_query, MYSQLI_ASSOC);
  }

  function tep_db_result($result, $row, $field = '') {
    if ( $field === '' ) {
      $field = 0;
    }

    tep_db_data_seek($result, $row);
    $data = tep_db_fetch_array($result);

    return $data[$field];
  }

  function tep_db_num_rows($db_query) {
    return mysqli_num_rows($db_query);
  }

  function tep_db_data_seek($db_query, $row_number) {
    return mysqli_data_seek($db_query, $row_number);
  }

  function tep_db_insert_id($link = 'db_link') {
    global $$link;

    return mysqli_insert_id($$link);
  }

  function tep_db_free_result($db_query) {
    return mysqli_free_result($db_query);
  }

  function tep_db_fetch_fields($db_query) {
    return mysqli_fetch_field($db_query);
  }

  function tep_db_output($string) {
    return htmlspecialchars($string);
  }

  function tep_db_input($string, $link = 'db_link') {
    global $$link;

    return mysqli_real_escape_string($$link, $string);
  }

  function tep_db_prepare_input($string) {
    if (is_string($string)) {
      return trim(stripslashes($string));
    } elseif (is_array($string)) {
      reset($string);
      while (list($key, $value) = each($string)) {
        $string[$key] = tep_db_prepare_input($value);
      }
      return $string;
    } else {
      return $string;
    }
  }

  function tep_db_affected_rows($link = 'db_link') {
    global $$link;

    return mysqli_affected_rows($$link);
  }

  function tep_db_get_server_info($link = 'db_link') {
    global $$link;

    return mysqli_get_server_info($$link);
  }

  if ( !function_exists('mysqli_connect') ) {
    define('MYSQLI_ASSOC', MYSQL_ASSOC);

    function mysqli_connect($server, $username, $password, $database) {
      if ( substr($server, 0, 2) == 'p:' ) {
        $link = mysql_pconnect(substr($server, 2), $username, $password);
      } else {
        $link = mysql_connect($server, $username, $password);
      }

      if ( $link ) {
        mysql_select_db($database, $link);
      }

      return $link;
    }

    function mysqli_connect_errno($link = null) {
      if ( is_null($link) ) {
        return mysql_errno();
      }

      return mysql_errno($link);
    }

    function mysqli_connect_error($link = null) {
      if ( is_null($link) ) {
        return mysql_error();
      }

      return mysql_error($link);
    }

    function mysqli_set_charset($link, $charset) {
      if ( function_exists('mysql_set_charset') ) {
        return mysql_set_charset($charset, $link);
      }
    }

    function mysqli_close($link) {
      return mysql_close($link);
    }

    function mysqli_query($link, $query) {
      return mysql_query($query, $link);
    }

    function mysqli_errno($link = null) {
      if ( is_null($link) ) {
        return mysql_errno();
      }

      return mysql_errno($link);
    }

    function mysqli_error($link = null) {
      if ( is_null($link) ) {
        return mysql_error();
      }

      return mysql_error($link);
    }

    function mysqli_fetch_array($query, $type) {
      return mysql_fetch_array($query, $type);
    }

    function mysqli_num_rows($query) {
      return mysql_num_rows($query);
    }

    function mysqli_data_seek($query, $offset) {
      return mysql_data_seek($query, $offset);
    }

    function mysqli_insert_id($link) {
      return mysql_insert_id($link);
    }

    function mysqli_free_result($query) {
      return mysql_free_result($query);
    }

    function mysqli_fetch_field($query) {
      return mysql_fetch_field($query);
    }

    function mysqli_real_escape_string($link, $string) {
      if ( function_exists('mysql_real_escape_string') ) {
        return mysql_real_escape_string($string, $link);
      } elseif ( function_exists('mysql_escape_string') ) {
        return mysql_escape_string($string);
      }

      return addslashes($string);
    }

    function mysqli_affected_rows($link) {
      return mysql_affected_rows($link);
    }

    function mysqli_get_server_info($link) {
      return mysql_get_server_info($link);
    }
  }
?>

I don't understand : I use the original database.php from the OSC 2.3.1... (Copyright 2007).

 

When I use the database.php you posted, I have lot of errors (images disapeared, error mysql...). I can't use it...

Link to comment
Share on other sites

 

Did you get a fatal error in your PHP log when this happened? You probably just forgot to comment a bracket, }, or something.

 

But perhaps it's simpler to just replace the mysqli_prepared_query function in database.php. Replace it with the code below

    function mysqli_prepared_query( $sql, $typeDef = FALSE, $params = FALSE, $link = "db_link" ) {
      global $$link;

      if ( false === $typeDef || empty( $typeDef ) ) {
        return tep_db_fetch_all( $sql );
      }

      # Kiss Error Debugger
      $start_time = microtime( true );

      if ( $stmt = mysqli_prepare( $$link, $sql ) ) {
        if ( count( $params ) == count( $params, 1 ) ) {
          $params = array( $params );
          $multiQuery = FALSE;
        } else {
          $multiQuery = TRUE;
        }

        if ( $typeDef ) {
          $bindParams = array();
          $bindParamsReferences = array();
          $bindParams = array_pad( $bindParams, ( count( $params, 1 )-count( $params ) )/count( $params ), "" );
          foreach ( $bindParams as $key => $value ) {
            $bindParamsReferences[ $key ] = &$bindParams[ $key ];
          }
          array_unshift( $bindParamsReferences, $typeDef );
          $bindParamsMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_param' );
          $bindParamsMethod->invokeArgs( $stmt, $bindParamsReferences );
        }

        $result = array();
        foreach ( $params as $queryKey => $query ) {
          foreach ( $bindParams as $paramKey => $value ) {
            $bindParams[ $paramKey ] = $query[ $paramKey ];
          }
          $queryResult = array();
          if ( mysqli_stmt_execute( $stmt ) ) {
            $resultMetaData = mysqli_stmt_result_metadata( $stmt );
            if ( $resultMetaData ) {
              $stmtRow = array();
              $rowReferences = array();
              while ( $field = mysqli_fetch_field( $resultMetaData ) ) {
                $rowReferences[] = &$stmtRow[ $field->name ];
              }
              mysqli_free_result( $resultMetaData );
              $bindResultMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_result' );
              $bindResultMethod->invokeArgs( $stmt, $rowReferences );
              while ( mysqli_stmt_fetch( $stmt ) ) {
                $row = array();
                foreach ( $stmtRow as $key => $value ) {
                  $row[$key] = $value;
                }
                $queryResult[] = $row;
              }
              mysqli_stmt_free_result( $stmt );
            } else {
              $queryResult[] = mysqli_stmt_affected_rows( $stmt );
            }
          } else {
            $queryResult[] = FALSE;
          }
          $result[ $queryKey ] = $queryResult;
        }
        mysqli_stmt_close( $stmt );
      } else {
        $result = FALSE;
      }

      # Kiss Error Debugger
      if ( class_exists( 'KissER' ) ) {
        $sql = interpolateQuery( $sql, $params[0] );
        KissER::q( round( ( microtime( true ) - $start_time ), 4 ), $sql );
      }

      if ( $multiQuery ) {
        return $result;
      } else {
        return $result[0];
      }
    }

Tried it, the admin dashboard keeps working now but when I select : advanced_statistics the screen is blank now

 

Error.log :

PHP Fatal error: Call to a member function query() on a non-object in /admin/advanced_statistics/general_functions.php on line 47

PHP Warning: file(includes/languages/dutch/modules/boxes/bm_categories2.php): failed to open stream: No such file or directory in /dynamic-sitemap.php on line 117

PHP Warning: file(includes/languages/dutch/modules/boxes/bm_partners.php): failed to open stream: No such file or directory in /dynamic-sitemap.php on line 117

PHP Fatal error: Call to a member function query() on a non-object in /admin/advanced_statistics/general_functions.php on line 47

******************************************************************

I've solved it !! I've replaced database.php with the original 2.3.3 version (I use OsCommerce 2.3.4)

 

Thanks for you help

Link to comment
Share on other sites

 

 

I don't understand : I use the original database.php from the OSC 2.3.1... (Copyright 2007).

 

When I use the database.php you posted, I have lot of errors (images disapeared, error mysql...). I can't use it...

 

 

I'm sorry, but then it seems like this Add-On will not work on OSC 2.3.1 without making modifications to it. :(

 

I didn't think they changed that much from earlier 2.3 versions. If you want, you could always upgrade to a newer osC version. Download the upgrade packages from http://www.oscommerce.com/Products (you find them at the bottom of the page under "Release History".

Link to comment
Share on other sites

Link to comment
Share on other sites

  • 3 weeks later...

jQuery/Ajax Advanced Statistics Rev2

 

Download Add-On here: http://addons.oscommerce.com/info/9286

 

 

New Features and changes in Revision 2

  • Fixed so it's possible to display more than one table at a time
  • Two levels of child tables - Months => Days => Hours
  • jQuery DateRange Picker
  • New Filter - Categories - Filter Statistics from selected categories (multiple selections possible)
  • New Filter - Products - Filter Statistics from selected product(s) (multiple selections possible)
  • New Filter - Customers - Filter Statistics from selected customer(s) (multiple selections possible)
  • New Filter - Custom Filter - Filter anything you want from any column in the 'orders' table ( E.g. Name, Company, City, Postcode, State, Country, Telephone, Payment Method, Currency.. )
  • Group by week
  • New Column - Display total # of products sold
  • Tabletools - Export to CSV/XLS Settings
  • AmCharts - Fixed charts with Pan/Zoom
  • AmCharts - Export to PNG/JPG/SVG
  • AmCharts - ChartCursor
  • AmCharts - Separate Axis for Products Sold
  • Settings - Your settings will now be saved with a Cookie and in the localStorage object aStat. So every time you get back to the Advanced Statistics page your previously selected filters and options will be selected.
Link to comment
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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.

×
×
  • Create New...