diff --git a/README.new.md b/README.new.md new file mode 100644 index 0000000..75c156c --- /dev/null +++ b/README.new.md @@ -0,0 +1,713 @@ +# SiteClass Verion 2.0 + +**SiteClass** is a PHP mini framework for simple, small websites. It can be esaly combined with other frameworks or templeting engines if needed. For small websites I feel that frameworks like Laravel or Meteor etc. are just too much. + +This project has several parts that can function standalone or combined. + +* Database.class.php : provides a wrapper for several different database engines. +* dbTables.class.php : uses the functionality of Database.class.php to make creating tables easy. +* ErrorClass.class.php : Error and Exception classes +* SiteClass.class.php : tools for making creating a site a little easier. The class provides methods to help with headers, banners, footers and more. + +The following database engines are provided as the following classes: + +1. dbMysqli.class.php : (rigorously tested) This is the latest PHP version of the MySql database engine. +2. dbSqlite.class.php : sqlite3 (used for the examples) + +There are a couple of additional databases but they have not be rigouously tested. + +## Disclamer + +To start, this framework is meant for Linux not Windows. I don't use Windows, like it or have it, +so nothing has been tried on Windows. + +I use Linux Mint which is an Ubuntu derivative which is a Debian derivative. +I have not tried this package on any distributions that do not evolve from Debian. + +## Install + +There are several ways to install this project. + +### Download The ZIP File + +Download the ZIP file from GitHub. Expand it and move the 'includes' directory somewhere. On a system with Apache2, +I usually put the 'includes' directory in the /var/www directory that Apache creates. +Apache also usually creates /var/www/html and makes this the default DocumentRoot. +I put the 'includes' directory just outside of the DocumentRoot. +In my servers I have /var/www and then have my virtual hosts off that directory. +That way the 'includes' directory is easily available to all of my virtual hosts. + +If you are testing with the PHP server I put a 'www' directory off my $HOME and put the 'includes' directory there. +I then make my test DocumentRoot off '~/www' like '~/www/test'. I `cd` to the test directory and +do `php -S localhost:8080`. I can then use my browser and goto `localhost:8080` and see my 'index.php' file. + +### Use Composer + +If you have Apache or Nginx installed then you should made your project root somewhere within your +DocumentRoot ('/var/www/html' for Apache2 on Ubuntu). Or if you want to make a seperate Apache virtual host with a +registered domain name you can make your new project in '/var/www'. + +Create a directory `mkdir myproject; cd myproject`, this is your project root directory. +Add the following to 'composer.json', just cut and past: + +```json +{ + "require": { + "bartonlp/site-class": "dev-master" + } +} +``` + +Then run + +```bash +composer install +``` + +**OR** you can just run + +```bash +composer require bartonlp/site-class:dev-master +``` + +which will create the 'composer.json' for you and load the package like 'composer install' above. + +In your PHP file add `require_once($PATH_TO_VENDOR . '/vendor/autoload.php');` +where '$PATH' is the path to the 'vendor' directory like './' or '../' etc. + +There are some example files in the 'examples' directory at '$PATH_TO_VENDOR/vendor/bartonlp/site-class/examples'. + +## Examples + +The code shown below can be found in the 'examples' directory at http://github.com/bartonlp/site-class or +from your project root at 'vendor/bartonlp/site-class/examples'. There is an 'EXAMPLES.md' and 'EXAMPLES.html' +in the 'examples' directory. + +

The code in the 'examples' directory has actually been tested and runs. +The code in this README was originally copied in from the examples code but may have changed for some reason. +Therefore you should use the examples code rather than doing a copy and past from this README.

+ +If you have Apache or Nginx installed then you should have made your project root somewhere within your DocumentRoot, +for example '/var/www/html/myproject'. + +If you don't have Apache or Nginx installed on your computer you can use the PHP server. +Do the following from your project root: + +```bash +php -S localhost:8080 +``` + +Then use your browser by entering `http://localhost:8080/vendor/bartonlp/site-class/README.html` +in the browsers location bar. + +The code in the 'examples' directory uses the **sqlite3** database engine. +There should be a 'test.sdb' database file in the 'examples' directory already. + +I have included a 'sqlite.sql' file that can be run from the command line if you want to recreate the 'members' table. + +You will need to get sqlite3 and get the PHP sqlite packages along with mysql etc. +From the command line in the directory where the SiteClass was downloaded: + +```bash +$ cd examples +$ sqlite3 test.sdb +sqlite> drop table members; +sqlite> .read sqlite.sql +sqlite> .table +members +sqlite> select rowid,* from members; +1|Big|Joe +2|Little|Joe +3|Barton|Phillips +4|Someone|Else +sqlite> .quit +$ +``` + +This should create a new 'members' table in the 'test.sdb' database. + +
+ +There are a number of ways to use the framework: + +**First** you can just use the SiteClass all by itself. + +```php +getPageTopBottom(); +echo <<Test 1 +

Hello World

+$footer +EOF; +``` + +That is the simplest usage. You get a generic head and a genericfooter. No database or other stuff. + +
+ +You can extend this by adding a database either by instantiating the 'Database' class directly or indirectly. + +```php + "2016 Barton L. Phillips", + 'memberTable' => 'members', + // Add dbinfo to the $_site and SiteClass will instantiate the Database for you + 'dbinfo' => array( + 'database' => 'test.sdb', + 'engine' => 'sqlite3', + ), +); + +$S = new SiteClass($_site); + +list($top, $footer) = $S->getPageTopBottom(); + +// Do some database operations + +$S->query("select fname||' '||lname) from {$_site['memberTable']}"; +$names = ''; + +while(list($name) = $S->fetchrow('num')) { // fetch a row with numeric indices. + $names .= "$name
"; +} + +echo <<Test 2 +

$names

+$footer +EOF; +``` + +The above example uses the 'query' and 'fetchrow' methods to do some database operations. + +
+ +The database could also be instantiated explicitly as follows: + +```php + "2015 Barton L. Phillips", + 'memberTable' => 'members', +); + +$dbinfo = array( + 'database' => 'test.sdb', + 'engine' => 'mysqli' +); + +$_site['databaseClass'] = new Database($dbinfo); + +// by adding to the $siteinfo arrays 'databaseClass' element we let SiteClass +// know that the database is active. + +$S = new SiteClass($_site); + +list($top, $footer) = $S->getPageTopBottom(); + +// Do some database operations + +$S->query("select fname||' '||lname from {$siteinfo['memberTable']}"); + +$names = ''; + +while(list($name) = $S->fetchrow('num')) { + $names .= "$name
"; +} + +echo <<Test 3 +

$names

+
+$footer +EOF; +``` + +
+ +You can also use the 'siteload.php' file to load the json file 'mysitemap.json' to further automate working +with the framework. This file is in the 'includes' directory. There is a 'mysitemap.json.php' file that is well commented. +You can uncomment sections of this file or add items as needed. + +You can run this file as a CLI program and it will output to 'stdout'. Create your 'mysitemap.json' file as follows: + +```bash +./mysitemap.json.php >mysitemap.json +``` + +Copy the created file to your project directory. +There is already a 'mysitemap.json' file in the 'examples' directory. + +I set the Apache2 environment variable 'SITELOAD' to point to my 'siteload.php' file in +'vendor/bartonlp/site-class/includes'. You can add it to your '/etc/apache2/apache2.conf', to an apache2 virtual host +or to your '.htaccess' file. I will assume you have done this in the following examples. + +```bash +SetEnv SITELOAD /var/www/vendor/bartonlp/site-class/includes/siteload.php +``` + +This example uses 'SITELOAD', 'query' and 'fetchrow': + +```php +className($_site); + +list($top, $footer) = $S->getPageTopBottom(); + +// Do some database operations + +$S->query("select concat(fname, ' ', lname) from {$siteinfo['memberTable']}"; + +$names = ''; + +while(list($name) = $S->fetchrow('num')) { + $names .= "$name
"; +} + +echo <<Test 4 +

$names

+$footer +EOF; +``` + +
+ +In addition to the SiteClass and Database classes there are several others classes in the 'database-engins' directory: + +* ErrorClass +* SqlException +* dbTables +* and a file with helper functions ('helper-functions.php'). + +
+ +The dbTables class uses the Database class to make creating tables simple. For example: + +```php +className($_site); +$T = new dbTables($S); + +// Pass some info to getPageTopBottom method + +$h->title = "Table Test 5"; // Goes in the +$h->banner = "

Test 5

"; // becomes the
section + +// Add some local css to but a border and padding on the table + +$h->css = << +main table * { + padding: .5em; + border: 1px solid black; +} + +EOF; + +list($top, $footer) = $S->getPageTopBottom($h); + +// create a table from the database table 'memberTable' + +$sql = "select * from $S->memberTable"; +list($tbl) = $T->maketable($sql); +echo << +

Create a table from the members database table

+

The members table follows:

+$tbl + +
+$footer +EOF; +``` + +The 'maketable' method takes several optional arguments to help setup the table. +Using the options you can give your table an id or class or set any other attributes. +You can also pass a 'callback' function which can modify the rows as they are selected +(see the 'insert-update.php' file in the 'examples' directory for more information). + +
+ +## The 'mysitemap.json' File + +The 'mysitemap.json' file is the site configuration file. 'siteload.php' loads the 'mysitemap.json' file +that is in the current directory. If a 'mysitemap.json' file is not found an exception is thrown. + +Once a 'mysitemap.json' file is found the information in it is read in via 'require_once'. +The information from the 'mysitemap.json' file is returned as a PHP object. + +You can generate a 'mysitemap.json' file by running 'mysitemap.json.php' and redirecting the output to 'mysitemap.json'. + +My usual directory structure starts under a 'www' subdirectory. On an Apache2 host the structure looks like this: + +```plain +/var/www/vendor // this is the 'composer' directory where the 'bartonlp/site-class' resides +/var/www/html // this is where your php files and js, css etc. + // directories live +/var/www/html/includes // this is where 'headFile', 'bannerFile', + // 'footerFile' and child classes live +``` + +If I have multiple virtual hosts they are all off the '/var/www' directory instead of a single 'html' directory. + +### How the xxxFile files look + +In the 'mysitemap.json' file there can be three elements that describe the location of special files. +These files are 1) 'headFile', 2) 'bannerFile' and 3) 'footerFile'. + +I put the three special file in my '/var/www/html/includes' directory (where 'html' may be one of your virtual hosts +and not named 'html'). + +Here is an example of my 'headFile': + +```php + + {$arg['title']} + + + + + + + +{$arg['link']} + + +{$arg['extra']} +{$arg['script']} +{$arg['css']} + +EOF; +``` + +These 'xxxFile' files return their contents. +The $arg array is created form the argument passed to the 'getPageTopBottom' method. +The 'getPageTopBottom' method also has access to the SiteClass '$this' property. + +You will see if you delve into the SiteClass code that many things can be passed to the getPageTopBottom method, +and the various sub-methods, but the standard things are: + +* title +* desc +* link +* extra +* script +* css + +As you saw in example 5 above (test5.php in the 'examples' directory) I passed a '$h' object to 'SiteClass'. +For example it might look like this: + +```php +$h->title = 'my title'; +$h->desc = 'This is the description'; +$h->link = ''; +$h->extra = ''; +$h->script = ''; +$h->css = ''; +$S = new SiteClass($h); +``` + +As you can see in the 'headFile' example the '$this' can also be used as in '$this->copyright'. +Any of the public, protected or private '$this' properties can be used in any of the special files as they +are all included within 'SiteClass.class.php'. + +As these special files are PHP files you can do anything else that you need to, +including database queries. Just remember that you need to use '$this'. +For example, to do a query do `$this->query($sql);` not `$S->query($sql);`. +You can't use the variable from your project file that you created via the `$S = new SiteClass($h);` +because it is NOT within scope. + +I usually call these files 'head.i.php', 'banner.i.php' and 'footer.i.php' but you can name them anything you like. +In the 'mysitemap.json' just add the full path to the file. For example: + +```json +{ + "siteDomain": "example.com", + "siteName": "Example", + "mainTitle": "Test Site", + "className": "SiteClass", + "copyright": "2016 Barton L. Phillips", + "author": "Barton L. Phillips, mailto:bartonphillips@gmail.com", + "masterdb": "your_master_database", + "dbinfo": { + "host": "localhost", + "user": "username", + "password": "password", + "database": "yourPrimaryDatabase", + "engine": "mysqli" + }, + "headFile": "/var/www/html/includes/head.i.php", + "bannerFile": "/var/www/html/includes/banner.i.php", + "footerFile": "/var/www/html/includes/footer.i.php", + "count": true, + "countMe": true, + "myUri": "yourUri", + "EMAILADDRESS": "email@example.com", + "EMAILRETURN": "email@example.com", + "EMAILFROM": "webmaster@example.com" +} +``` + +There is a default for the head, banner and footer section if you do not have special files. +The DOCTYPE is by default but that can be altered via an argument to the 'getPageTopBottom' +method (`$h->doctype='xxx';`). + +Creating the special files make the tedious boiler plate simple and yet configureable via the $arg array. + +
+ +# Doing Page Counting and Analysis + +If you want to do page counting and analysis there are several MySql tables that you can use. The MySql schema for these +tables is in the *mysql.schema* file in the repository. + +The tables are: + +* bots : the SiteClass has logic to try to determin which user agents might be robots. +* bots2 : similar to bots but has a 'site' and 'date' field. +* logagent : logs the IpAddress, and User Agent. +* logagent2 : a short term version of lagagent. +* daycounts : counts the number of hits per day +* counter : counts the number of hits per site per file. +* counter2 : counts the number of hits per site per file per day. +* tracker : trackes accesses by site, page etc. + +Here are the schemas of the tables: + +```sql +CREATE TABLE `bots` ( + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL DEFAULT '', + `count` int(11) DEFAULT NULL, + `robots` int(5) DEFAULT '0', + `who` varchar(255) DEFAULT NULL, + `creation_time` datetime DEFAULT NULL, + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`ip`,`agent`), + KEY `ip` (`ip`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `bots2` ( + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL DEFAULT '', + `date` date NOT NULL DEFAULT '0000-00-00', + `site` varchar(50) NOT NULL DEFAULT '', + `which` int(5) NOT NULL DEFAULT '0', + `count` int(11) DEFAULT NULL, + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`ip`,`agent`,`date`,`site`,`which`), + KEY `ip` (`ip`), + KEY `agent` (`agent`), + KEY `site` (`site`), + KEY `ip_2` (`ip`), + KEY `date` (`date`), + KEY `site_2` (`site`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `logagent` ( + `site` varchar(25) NOT NULL DEFAULT '', + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL, + `count` int(11) DEFAULT NULL, + `id` int(11) DEFAULT NULL, + `created` datetime DEFAULT '0000-00-00 00:00:00', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`ip`,`agent`), + KEY `ip` (`ip`), + KEY `site` (`site`), + KEY `agent` (`agent`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `logagent2` ( + `site` varchar(25) NOT NULL DEFAULT '', + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL, + `count` int(11) DEFAULT NULL, + `id` int(11) DEFAULT NULL, + `created` datetime DEFAULT '0000-00-00 00:00:00', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`ip`,`agent`), + KEY `agent` (`agent`), + KEY `site` (`site`), + KEY `ip` (`ip`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `daycounts` ( + `site` varchar(50) NOT NULL DEFAULT '', + `date` date NOT NULL, + `real` int(11) DEFAULT '0', + `bots` int(11) DEFAULT '0', + `members` int(11) DEFAULT '0', + `visits` int(11) DEFAULT NULL, + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `counter` ( + `filename` varchar(255) NOT NULL, + `site` varchar(50) NOT NULL DEFAULT '', + `ip` varchar(20) DEFAULT NULL, + `agent` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT NULL, + `realcnt` int(11) DEFAULT '0', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`filename`,`site`), + KEY `site` (`site`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `counter2` ( + `site` varchar(50) NOT NULL DEFAULT '', + `date` date NOT NULL DEFAULT '0000-00-00', + `filename` varchar(255) NOT NULL DEFAULT '', + `count` int(11) DEFAULT '0', + `members` int(11) DEFAULT '0', + `bots` int(11) DEFAULT '0', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`date`,`filename`), + KEY `site` (`site`), + KEY `date` (`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `tracker` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `site` varchar(25) DEFAULT NULL, + `page` varchar(255) NOT NULL DEFAULT '', + `ip` varchar(40) DEFAULT NULL, + `agent` varchar(255) DEFAULT NULL, + `starttime` datetime DEFAULT NULL, + `endtime` datetime DEFAULT NULL, + `difftime` time DEFAULT NULL, + `refid` int(11) DEFAULT '0', + `isJavaScript` int(5) DEFAULT '0', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `site` (`site`), + KEY `ip` (`ip`), + KEY `agent` (`agent`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +``` + +If you look at *SiteClass* you will see several methods in the constructor: + +*$this->trackbots(); +*$this->tracker(); +*$this->doanalysis(); +*$this->logagent(); +*$this->counter(); + +If you look at these methods you will see that they are protected by a check of the database to see if the tables +exists in the database. If the table does not exist an 'error_log' message is output. +You can prevent the error message by setting "noErrorLog": "true" in the 'mysitemap.json' file. + +
+ +# Tests + +In the 'tests' directory there are a series of mostly database engine tests. If you want to test MySql +you will need to first install the packages (both OS and PHP5) and then configure each with a user and password etc. +Setting up the databases is beyond the scope of this README. +The tests are set up for an account with user 'siteclass' and password 'siteclass' with database 'siteclass' +(no single quotes of course). + +
+ +# Class Methods + +While there are a number of methods for each of the major classes there are really only a small handful you will use on a regular bases. The ones most used have some documentation with them. + +## SiteClass methods: + +* constructor +* public function setSiteCookie($cookie, $value, $expire, $path="/") +* public function getId() // if a memberTable +* public function setId($id) // if a memberTable +* public function getIp() +* public function getPageTopBottom($h, $b=null) +This is the most used method. It takes one or two arguments which can be string|array|object. +$h can have 'title', 'desc', 'banner' and a couple of other less used options. +$b is for the footer or bottom. I sometimes pass a <hr> but you can also pass a 'msg', 'msg1', 'msg2' (see the code). I usually put things into the 'footerFile' but on occasions a page needs something extra. +This method calls getPageHead(), getBanner(), getFooter(). +* public function getPageTop($header, $banner=null, $bodytag=null) +* public function getDoctype() +* public function getPageHead(/*$title, $desc=null, $extra=null, $doctype, $lang*/) +* public function getPageBanner($mainTitle, $nonav=false, $bodytag=null) +* public function getPageFooter(/* mixed */) +* public function \__toString() +* A number of 'protected' methods and properties that can be used in a child class. + +## Database methods: + +* constructor +* public function getDb() +* public function query($query) +This is the workhourse of the database. It is used for 'select', 'update', 'insert' and basically anything you need to do like 'drop', 'alter' etc. $query is the sql statement. +* public function fetchrow($result=null, $type="both") +Probably the second most used method. If it follows the 'query' the $result is not needed. The only time $result is needed is if there are other queries in a while loop. In that case you need to get the result of the query by calling the getResult() method before running the while loop. +The $type can be 'assoc', 'num' or default 'both'. 'assoc' returns only an associative array, while 'num' return a numeric array. I usually use a numeric array with + +```php +while(list($name, $email) = $S->fetchrow('num')) { ... } +``` + +* public function queryfetch($query, $retarray=false) +* public function getLastInsertId() +After an 'insert' this method returns the new row primary key id. +* public function getResult() +Returns the result object from the last 'query'. Usually not needed. +* public function escape($string) +* public function escapeDeep($value) +* public function getNumRows($result=null) +* public function prepare($query) +I hardly ever use prepare(), bindParam(), bindResults() or execute() so they are not as well tested as the other methods. +* public function bindParam($format) +* public function bindResults($format) +* public function execute() +* public function getErrorInfo() + +The database methods are implemented for all supported engines. There are some minor behavioral differences, for example in the syntax the engine queries uses or the return values. For example sqlite3 does not support a number of rows returned functionality and there are also several (many) syntactial differenced between sqlite and mysql when it comes to supported functions etc. (caviat emptor). + +## dbTables methods: + +* constructor +* public function makeresultrows($query, $rowdesc, array $extra=array()) +* public function maketable($query, array $extra=null) +$extra is an optional assoc array: $extra['callback'], $extra['callback2'], $extra['footer'] and $extra['attr']. +$extra['attr'] is an assoc array that can have attributes for the tag, like 'id', 'title', 'class', 'style' etc. +$extra['callback'] function that can modify the header after it is filled in. +$extra['footer'] a footer string +@return array [{string table}, {result}, {num}, {hdr}, table=>{string}, result=>{result}, + num=>{num rows}, header=>{hdr}] + or === false + +## Contact Me + +Barton Phillips : bartonphillips@gmail.com +Copyright © 2015 Barton Phillips diff --git a/composer.json b/composer.json index 6f3594f..6d55bb8 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "includes/database-engines" ], "files": [ - "includes/database-engines/helper-functions.php" + "includes/database-engines/helper-functions.php", + "includes/siteload.php" ] } } diff --git a/dot-sitemap.php.example b/dot-sitemap.php.example deleted file mode 100644 index bb939b1..0000000 --- a/dot-sitemap.php.example +++ /dev/null @@ -1,123 +0,0 @@ - 'localhost', - 'user' => 'barton', - 'password' => '7098653', - 'database' => 'barton', - 'engine' => 'mysqli' - ); - -// SiteClass information -// 'siteDomain' should be your domain name like 'bartonphillips.dyndns.org' without subdomains like -// www. -// 'siteName' is how you will call your host. -// 'copyright' obvious -// 'className' the class name you instantiate in your php files. For example if you use SiteClass -// directly use 'className'=>'SiteClass' if you extend SiteClass via MyClass then -// 'className'=>'MyClass'. -// 'memberTable' if you have a table that has member or user information. If you have a -// 'memberTable' it must have several fields. -// You can add additional fields and if you do so you will probably need to -// extend SiteClass. See SiteClsss.class.php for a list of the required fields. -// Also, if 'memberTable' is defined you also need a 'memberpagecnt' table! You can pass -// 'nomemberpagecnt' true to the SiteClass constructor if you have a member table and you -// do NOT want to count members. -// 'headFile' SiteClass can provide a generic section but you can provide your own -// customized section in a file. -// 'bannerFile' as above. -// 'footerFile' as above. -// 'dbinfo' if you have a database above ($dbinfo). See info on the Database class and -// 'databaseClass' passed to the SiteClass constructor. -// 'count' should hits be counted. If yes then your database must have a 'counter' table as -// described in SiteInfo.class.php. If 'count' is ture then the following tables are required: -// counter, daycount and tracker. If you don't have these tables in your database DON'T -// enable 'count'! 'count' is false by default. -// 'countMe' should the webmaster or someone special be counted or not. 'countMe' default false. -// 'myUrl' the webmaster or someone special's domain. -// You can extend the $siteinfo array to include things you may in an extended child class of -// SiteInfo. -// A $siteinfo array must be passed to SiteClass like this for example: -// $S = new SiteClass($siteinfo); -// You can either extend the array here or before you pass it to the SiteClass class. - -$siteinfo = array('siteDomain' => "localhost", - 'siteName' => 'Vbox Localhost', - 'mainTitle' => "Test Site", - //'emailDomain' => null, - 'path' => "/var/www/html", - 'className' => "SiteClass", - 'copyright' => "2016 Barton L. Phillips", - 'author' => "Barton L. Phillips, mailto:bartonphillips@gmail.com", - //'memberTable' => null, - 'masterdb' => 'barton', // This is where bots, tracker, counter and logagent are. - //'headFile' => SITE_INCLUDES."/head.i.php", - //'bannerFile' => SITE_INCLUDES."/banner.i.php", - //footerFile => SITE_INCLUDES."/footer.i.php" - 'dbinfo' => $dbinfo, - 'count' => true, // NOTE this defaults to false - 'countMe' => true, // Count BLP. Also defaults to false - //'daycountwhat' => 'all', // what should we daycount? Can be a filename, all, or an array of filenames. - //'analysis' => true, // update the barton.analysis table - //'trackerImg1' => "/images/blp-image.png", // script - //'trackerImg2' => "/images/146624.png", // normal - 'myUri' => "bartonphillips.dyndns.org", - 'EMAILADDRESS' => EMAILADDRESS, - 'EMAILRETURN' => EMAILRETURN, - 'EMAILFROM' => EMAILFROM, - ); - diff --git a/examples/.sitemap.php b/examples/.sitemap.php deleted file mode 100644 index 0ac54e2..0000000 --- a/examples/.sitemap.php +++ /dev/null @@ -1,128 +0,0 @@ - 'test.sdb', 'engine' => 'sqlite3'); - break; - case 'pgsql': - $dbinfo = array('host'=>'localhost', 'user'=>'barton', 'password'=>'7098653', - 'database' => 'barton', 'engine' => 'pgsql'); - break; - case 'pdo_pgsql': - $dbinfo = array('host'=>'localhost', 'user'=>'barton', 'password'=>'7098653', - 'database' => 'barton', 'engine' => 'pdo_pgsql'); - break; - case 'pdo_sqlite': - $dbinfo = array('database' => 'test.sdb', 'engine' => 'pdo_sqlite'); - break; - case 'mysql': - $dbinfo = array('host'=>'localhost', 'user'=>'barton', 'password'=>'7098653', - 'database' => 'barton', 'engine' => 'mysql'); - break; - case 'mysqli': - $dbinfo = array('host'=>'localhost', 'user'=>'barton', 'password'=>'7098653', - 'database' => 'barton', 'engine' => 'mysqli'); - break; -} - -// SiteClass information -// 'siteDomain' should be your domain name like 'bartonphillips.dyndns.org' without subdomains like -// www. -// 'siteName' is how you will call your host. -// 'copyright' obvious -// 'className' the class name you instantiate in your php files. For example if you use SiteClass -// directly use 'className'=>'SiteClass' if you extend SiteClass via MyClass then -// 'className'=>'MyClass'. -// 'memberTable' if you have a table that has member or user information. If you have a -// 'memberTable' it must have several fields. You can add additional fields and if you do so you -// will probably need to extend SiteClass. See SiteClsss.class.php for a list of the required -// fields. -// 'headFile' SiteClass can provide a generic section but you can provide your own -// customized section in a file. -// 'bannerFile' as above. -// 'footerFile' as above. -// 'dbinfo' if you have a database above ($dbinfo). See info on the Database class and -// 'databaseClass' passed to the SiteClass constructor. -// 'count' should hits be counted. If yes then your database must have a 'counter' table as -// described in SiteInfo.class.php. -// 'countMe' should the webmaster or someone special be counted or not. -// 'myUrl' the webmaster or someone special's domain. -// You can extend the $siteinfo array to include things you may in an extended child class of -// SiteInfo. -// A $siteinfo array must be passed to SiteClass like this for example: -// $S = new SiteClass($siteinfo); -// You can either extend the array here or before you pass it to the SiteClass class. - -$siteinfo = array('siteDomain' => "localhost", - 'siteName' => 'Vbox Localhost', - 'mainTitle' => "Test Site", - //'emailDomain' => null, - 'path' => "/var/www/html", - 'className' => "SiteClass", - 'copyright' => "2016 Barton L. Phillips", - 'author' => "Barton L. Phillips, mailto:bartonphillips@gmail.com", - //'memberTable' => null, - 'masterdb' => 'barton', // This is where bots, tracker, counter and logagent are. - //'headFile' => SITE_INCLUDES."/head.i.php", - //'bannerFile' => SITE_INCLUDES."/banner.i.php", - //footerFile => SITE_INCLUDES."/footer.i.php" - 'dbinfo' => $dbinfo, - 'count' => true, // NOTE this defaults to false - 'countMe' => true, // Count BLP. Also defaults to false - //'daycountwhat' => 'all', // what should we daycount? Can be a filename, all, or an array of filenames. - //'analysis' => true, // update the barton.analysis table - //'trackerImg1' => "/images/blp-image.png", // script - //'trackerImg2' => "/images/146624.png", // normal - 'myUri' => "bartonphillips.dyndns.org", - 'EMAILADDRESS' => EMAILADDRESS, - 'EMAILRETURN' => EMAILRETURN, - 'EMAILFROM' => EMAILFROM, - ); - diff --git a/examples/mysitemap.json b/examples/mysitemap.json new file mode 100644 index 0000000..d438015 --- /dev/null +++ b/examples/mysitemap.json @@ -0,0 +1,18 @@ +{ + "siteDomain": "localhost", + "siteName": "YourSiteName", + "mainTitle": "Title", + "className": "SiteClass", + "copyright": "2016 Barton L. Phillips", + "masterdb": "your_database_name", + "dbinfo": { + "host": "localhost", + "user": "username", + "password": "password", + "database": "yourdatabase", + "engine": "mysqli" + }, + "count": true, + "countMe": true, + "myUri": "bartonphillips.dyndns.org", +} \ No newline at end of file diff --git a/includes/SiteClass.class.php b/includes/SiteClass.class.php index 6d9743a..a83971b 100644 --- a/includes/SiteClass.class.php +++ b/includes/SiteClass.class.php @@ -551,7 +551,7 @@ public function getPageHead(/*$title, $desc=null, $extra=null, $doctype, $lang*/ } elseif(is_array($a)) { $arg = $a; } else { - error_log("Error: getPageHead() argument no valid: ". var_export($a, true)); + debug("Error: getPageHead() argument no valid: ". var_export($a, true)); throw(new Exception("Error: getPageHead() argument no valid: ". var_export($a, true))); } } elseif($n > 1) { @@ -903,10 +903,10 @@ protected function trackbots() { "on duplicate key update count=count+1, lasttime=now()"); } } else { - error_log("$this->siteName: $this->self: table bots2 does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table bots2 does not exist in the $this->masterdb database"); } } else { - error_log("$this->siteName: $this->self: table bots does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table bots does not exist in the $this->masterdb database"); } } @@ -936,14 +936,14 @@ protected function tracker() { $java = 0x2000; // This is the robots tag } - //error_log("SiteClass: tracker, $this->siteName, $this->ip, $agent, $this->self"); + //debug("SiteClass: tracker, $this->siteName, $this->ip, $agent, $this->self"); $this->query("insert into $this->masterdb.tracker (site, page, ip, agent, starttime, isJavaScript, lasttime) ". "values('$this->siteName', '$this->requestUri', '$this->ip','$agent', now(), $java, now())"); $this->LAST_ID = $this->getLastInsertId(); } else { - error_log("$this->siteName: $this->self: table tracker does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table tracker does not exist in the $this->masterdb database"); } } @@ -978,7 +978,7 @@ protected function doanalysis() { "on duplicate key update count=count+1, lasttime=now()"); } } else { - error_log("$this->siteName: $this->self: table analysis and/or analysis2 do not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table analysis and/or analysis2 do not exist in the $this->masterdb database"); } } } @@ -999,7 +999,7 @@ protected function setblpip() { list($ok) = $this->fetchrow('num'); if($ok == 0) { - error_log("$this->siteName: $this->self: table blpip does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table blpip does not exist in the $this->masterdb database"); return; } @@ -1049,7 +1049,7 @@ protected function counter() { $this->hitCount = ($cnt[0]) ? $cnt[0] : 0; } else { - error_log("$this->siteName: $this->self: table counter does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table counter does not exist in the $this->masterdb database"); } } @@ -1090,7 +1090,7 @@ protected function counter2() { } $this->query($sql); } else { - error_log("$this->siteName: $this->self: table bots does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table bots does not exist in the $this->masterdb database"); } } @@ -1116,7 +1116,7 @@ protected function daycount($inc) { list($ok) = $this->fetchrow('num'); if($ok == 0) { - error_log("$this->siteName: $this->self: table daycounts does not exist in the $this->masterdb database"); + debug("$this->siteName: $this->self: table daycounts does not exist in the $this->masterdb database"); return; } @@ -1217,7 +1217,7 @@ protected function logagent() { $this->query($sql); } else { - error_log("$this->siteName: $this->self: table logagent does not exist in the {$this->dbinfo['database']} database"); + debug("$this->siteName: $this->self: table logagent does not exist in the {$this->dbinfo['database']} database"); } // Do insert into logagent2 which has only the last n days @@ -1234,7 +1234,7 @@ protected function logagent() { $this->query($sql); } else { - error_log("$this->siteName: $this->self: table logagent2 does not exist in the {$this->dbinfo['database']} database"); + debug("$this->siteName: $this->self: table logagent2 does not exist in the {$this->dbinfo['database']} database"); } } @@ -1271,7 +1271,7 @@ protected function trackmember() { $this->query($sql); } else { - error_log("$this->siteName: $this->self: table $this->memberTable does not exist in the {$this->dbinfo['database']} database"); + debug("$this->siteName: $this->self: table $this->memberTable does not exist in the {$this->dbinfo['database']} database"); } // BLP 2014-09-16 -- add nomemberpagecnt @@ -1289,11 +1289,22 @@ protected function trackmember() { $this->query($sql); } else { - error_log("$this->siteName: $this->self: table memberpagecnt does not exist in the {$this->dbinfo['database']} database"); + debug("$this->siteName: $this->self: table memberpagecnt does not exist in the {$this->dbinfo['database']} database"); } } } } + + /* + * debug() + */ + + protected function debug($msg) { + if($this->noErrorLog === true) { + return; + } + error_log($msg); + } } // End of Class //----------------- diff --git a/includes/database-engines/ErrorClass.class.php b/includes/database-engines/ErrorClass.class.php index 81917e2..3e3c6f4 100644 --- a/includes/database-engines/ErrorClass.class.php +++ b/includes/database-engines/ErrorClass.class.php @@ -86,7 +86,7 @@ function my_errorhandler($errno, $errstr, $errfile, $errline, array $errcontext) // ErrorClass::$nohtml // ErrorClass::$noEmailErrs -function my_exceptionhandler(Exception $e) { +function my_exceptionhandler($e) { $cl = get_class($e); $error = $e; //->getMessage; // get the full error message diff --git a/includes/siteload.php b/includes/siteload.php new file mode 100644 index 0000000..ec95a43 --- /dev/null +++ b/includes/siteload.php @@ -0,0 +1,11 @@ + mysitemap.json +*/ + +// Example mysitemap.json + +// Email info + +define('EMAILADDRESS', "me@example.com"); +define('EMAILRETURN', "me@example.com"); +define('EMAILFROM', "webmaster@example.com"); + +// Database connection information. This specifies the database location, user, password, name and +// engine type. +// 'engine' is the type of database engine to use. Options are 'mysqli', or 'sqlite'. +// Change these to match your database information the following is just an example to be changed. + +$dbinfo = array('host' => 'localhost', + 'user' => 'your_user_name', + 'password' => 'password', + 'database' => 'your_database_name', + 'engine' => 'mysqli', // mysqli or sqlite + ); + +// SiteClass information +// 'siteDomain' should be your primary domain name like 'example.com' without subdomains like www. +// 'siteName' is how you will call your host. Should not have spaces. +// 'copyright' obvious +// 'className' the class name you instantiate in your php files. For example if you use SiteClass +// directly use 'className'=>'SiteClass' if you extend SiteClass via 'MyClass' then +// 'className'=>'MyClass'. +// 'memberTable' if you have a table that has member or user information. +// 'headFile' SiteClass can provide a generic section but you can provide your own +// customized section in a file. +// 'bannerFile' as above. +// 'footerFile' as above. +// 'dbinfo' if you have a database above ($dbinfo). See info on the Database class and +// 'databaseClass' passed to the SiteClass constructor. +// 'count' should hits be counted. If yes then your database must have a 'counter' table as +// described in SiteClass.class.php. 'count' is false by default. +// 'countMe' should the webmaster or someone special be counted or not. 'countMe' default false. +// 'myUrl' the webmaster or someone special's domain. +// You can extend the $_site array to include things you may want in an extended child class of +// SiteClass. +// +// A $_site array may be passed to SiteClass like this for example: +// $S = new SiteClass($_site); +// You can either extend the array here or before you pass it to the SiteClass class or SiteClass +// child. + +$_site = array('siteDomain' => "localhost", + 'siteName' => 'TheNameOfYourSite', // no spaces + //'mainTitle' => "Test Site", + //'emailDomain' => null, + //'path' => "/var/www/html", + 'className' => "SiteClass", + //'copyright' => "2016 Barton L. Phillips", + //'author' => "Barton L. Phillips, mailto:bartonphillips@gmail.com", + //'memberTable' => null, + //'masterdb' => 'your_master_database', // This is where tables used by multiple sites live + //'headFile' => "includes/head.i.php", + //'bannerFile' => "includes/banner.i.php", + //'footerFile' => "includes/footer.i.php" + 'dbinfo' => $dbinfo, + 'count' => true, // NOTE this defaults to false + 'countMe' => true, // Count BLP. Also defaults to false + //'daycountwhat' => 'all', // what should we daycount? Can be a filename, all, or an array of filenames. + //'analysis' => true, // update the barton.analysis table + //'trackerImg1' => "/images/blp-image.png", // script + //'trackerImg2' => "/images/146624.png", // normal + 'myUri' => "bartonphillips.dyndns.org", + 'EMAILADDRESS' => EMAILADDRESS, + 'EMAILRETURN' => EMAILRETURN, + 'EMAILFROM' => EMAILFROM, + ); + +$json = json_encode($_site, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + +echo "$json\n"; diff --git a/mysql.schema b/mysql.schema new file mode 100644 index 0000000..90f9f53 --- /dev/null +++ b/mysql.schema @@ -0,0 +1,170 @@ +-- +-- Table structure for table `bots` +-- + +DROP TABLE IF EXISTS `bots`; + +CREATE TABLE `bots` ( + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL DEFAULT '', + `count` int(11) DEFAULT NULL, + `robots` int(5) DEFAULT '0', + `who` varchar(255) DEFAULT NULL, + `creation_time` datetime DEFAULT NULL, + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`ip`,`agent`), + KEY `ip` (`ip`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `bots2` +-- + +DROP TABLE IF EXISTS `bots2`; + +CREATE TABLE `bots2` ( + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL DEFAULT '', + `date` date NOT NULL DEFAULT '0000-00-00', + `site` varchar(50) NOT NULL DEFAULT '', + `which` int(5) NOT NULL DEFAULT '0', + `count` int(11) DEFAULT NULL, + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`ip`,`agent`,`date`,`site`,`which`), + KEY `ip` (`ip`), + KEY `agent` (`agent`), + KEY `site` (`site`), + KEY `ip_2` (`ip`), + KEY `date` (`date`), + KEY `site_2` (`site`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `counter` +-- + +DROP TABLE IF EXISTS `counter`; + +CREATE TABLE `counter` ( + `filename` varchar(255) NOT NULL, + `site` varchar(50) NOT NULL DEFAULT '', + `ip` varchar(20) DEFAULT NULL, + `agent` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT NULL, + `realcnt` int(11) DEFAULT '0', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`filename`,`site`), + KEY `site` (`site`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `counter2` +-- + +DROP TABLE IF EXISTS `counter2`; + +CREATE TABLE `counter2` ( + `site` varchar(50) NOT NULL DEFAULT '', + `date` date NOT NULL DEFAULT '0000-00-00', + `filename` varchar(255) NOT NULL DEFAULT '', + `count` int(11) DEFAULT '0', + `members` int(11) DEFAULT '0', + `bots` int(11) DEFAULT '0', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`date`,`filename`), + KEY `site` (`site`), + KEY `date` (`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `daycounts` +-- + +DROP TABLE IF EXISTS `daycounts`; + +CREATE TABLE `daycounts` ( + `site` varchar(50) NOT NULL DEFAULT '', + `date` date NOT NULL, + `real` int(11) DEFAULT '0', + `bots` int(11) DEFAULT '0', + `members` int(11) DEFAULT '0', + `visits` int(11) DEFAULT NULL, + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `logagent` +-- + +DROP TABLE IF EXISTS `logagent`; + +CREATE TABLE `logagent` ( + `site` varchar(25) NOT NULL DEFAULT '', + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL, + `count` int(11) DEFAULT NULL, + `id` int(11) DEFAULT NULL, + `created` datetime DEFAULT '0000-00-00 00:00:00', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`ip`,`agent`), + KEY `ip` (`ip`), + KEY `site` (`site`), + KEY `agent` (`agent`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `logagent2` +-- + +DROP TABLE IF EXISTS `logagent2`; + +CREATE TABLE `logagent2` ( + `site` varchar(25) NOT NULL DEFAULT '', + `ip` varchar(40) NOT NULL DEFAULT '', + `agent` varchar(255) NOT NULL, + `count` int(11) DEFAULT NULL, + `id` int(11) DEFAULT NULL, + `created` datetime DEFAULT '0000-00-00 00:00:00', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`site`,`ip`,`agent`), + KEY `agent` (`agent`), + KEY `site` (`site`), + KEY `ip` (`ip`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `myip` +-- + +DROP TABLE IF EXISTS `myip`; + +CREATE TABLE `myip` ( + `blpIp` varchar(40) NOT NULL DEFAULT '', + `createtime` datetime DEFAULT NULL, + PRIMARY KEY (`blpIp`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `tracker` +-- + +DROP TABLE IF EXISTS `tracker`; + +CREATE TABLE `tracker` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `site` varchar(25) DEFAULT NULL, + `page` varchar(255) NOT NULL DEFAULT '', + `ip` varchar(40) DEFAULT NULL, + `agent` varchar(255) DEFAULT NULL, + `starttime` datetime DEFAULT NULL, + `endtime` datetime DEFAULT NULL, + `difftime` time DEFAULT NULL, + `refid` int(11) DEFAULT '0', + `isJavaScript` int(5) DEFAULT '0', + `lasttime` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `site` (`site`), + KEY `ip` (`ip`), + KEY `agent` (`agent`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8;