Initial commit
This commit is contained in:
544
pluf/src/GeoIP.php
Normal file
544
pluf/src/GeoIP.php
Normal file
@@ -0,0 +1,544 @@
|
||||
<?php
|
||||
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
|
||||
/**
|
||||
* geoip.inc
|
||||
*
|
||||
* Copyright (C) 2007 MaxMind LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modified by Loic d'Anterroches to have the function names with the
|
||||
* right case GeoIP instead of geoip.
|
||||
*
|
||||
* Added GeoIP_countryOfRequest function. Using single quotes instead
|
||||
* of double.
|
||||
*
|
||||
* Downloaded 2007-11-26.
|
||||
*
|
||||
* @deprecated This file is deprecated, you should directly use the
|
||||
* PECL extension.
|
||||
*/
|
||||
define('GEOIP_COUNTRY_BEGIN', 16776960);
|
||||
define('GEOIP_STATE_BEGIN_REV0', 16700000);
|
||||
define('GEOIP_STATE_BEGIN_REV1', 16000000);
|
||||
define('GEOIP_STANDARD', 0);
|
||||
define('GEOIP_MEMORY_CACHE', 1);
|
||||
define('GEOIP_SHARED_MEMORY', 2);
|
||||
define('STRUCTURE_INFO_MAX_SIZE', 20);
|
||||
define('DATABASE_INFO_MAX_SIZE', 100);
|
||||
|
||||
define('GEOIP_COUNTRY_EDITION', 106);
|
||||
define('GEOIP_PROXY_EDITION', 8);
|
||||
define('GEOIP_ASNUM_EDITION', 9);
|
||||
define('GEOIP_NETSPEED_EDITION', 10);
|
||||
define('GEOIP_REGION_EDITION_REV0', 112);
|
||||
define('GEOIP_REGION_EDITION_REV1', 3);
|
||||
define('GEOIP_CITY_EDITION_REV0', 111);
|
||||
define('GEOIP_CITY_EDITION_REV1', 2);
|
||||
define('GEOIP_ORG_EDITION', 110);
|
||||
define('GEOIP_ISP_EDITION', 4);
|
||||
define('SEGMENT_RECORD_LENGTH', 3);
|
||||
define('STANDARD_RECORD_LENGTH', 3);
|
||||
define('ORG_RECORD_LENGTH', 4);
|
||||
define('MAX_RECORD_LENGTH', 4);
|
||||
define('MAX_ORG_RECORD_LENGTH', 300);
|
||||
define('GEOIP_SHM_KEY', 0x4f415401);
|
||||
define('US_OFFSET', 1);
|
||||
define('CANADA_OFFSET', 677);
|
||||
define('WORLD_OFFSET', 1353);
|
||||
define('FIPS_RANGE', 360);
|
||||
define('GEOIP_UNKNOWN_SPEED', 0);
|
||||
define('GEOIP_DIALUP_SPEED', 1);
|
||||
define('GEOIP_CABLEDSL_SPEED', 2);
|
||||
define('GEOIP_CORPORATE_SPEED', 3);
|
||||
|
||||
class GeoIP {
|
||||
var $flags;
|
||||
var $filehandle;
|
||||
var $memory_buffer;
|
||||
var $databaseType;
|
||||
var $databaseSegments;
|
||||
var $record_length;
|
||||
var $shmid;
|
||||
var $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
|
||||
'' => 0, 'AP' => 1, 'EU' => 2, 'AD' => 3, 'AE' => 4, 'AF' => 5,
|
||||
'AG' => 6, 'AI' => 7, 'AL' => 8, 'AM' => 9, 'AN' => 10, 'AO' => 11,
|
||||
'AQ' => 12, 'AR' => 13, 'AS' => 14, 'AT' => 15, 'AU' => 16, 'AW' => 17,
|
||||
'AZ' => 18, 'BA' => 19, 'BB' => 20, 'BD' => 21, 'BE' => 22, 'BF' => 23,
|
||||
'BG' => 24, 'BH' => 25, 'BI' => 26, 'BJ' => 27, 'BM' => 28, 'BN' => 29,
|
||||
'BO' => 30, 'BR' => 31, 'BS' => 32, 'BT' => 33, 'BV' => 34, 'BW' => 35,
|
||||
'BY' => 36, 'BZ' => 37, 'CA' => 38, 'CC' => 39, 'CD' => 40, 'CF' => 41,
|
||||
'CG' => 42, 'CH' => 43, 'CI' => 44, 'CK' => 45, 'CL' => 46, 'CM' => 47,
|
||||
'CN' => 48, 'CO' => 49, 'CR' => 50, 'CU' => 51, 'CV' => 52, 'CX' => 53,
|
||||
'CY' => 54, 'CZ' => 55, 'DE' => 56, 'DJ' => 57, 'DK' => 58, 'DM' => 59,
|
||||
'DO' => 60, 'DZ' => 61, 'EC' => 62, 'EE' => 63, 'EG' => 64, 'EH' => 65,
|
||||
'ER' => 66, 'ES' => 67, 'ET' => 68, 'FI' => 69, 'FJ' => 70, 'FK' => 71,
|
||||
'FM' => 72, 'FO' => 73, 'FR' => 74, 'FX' => 75, 'GA' => 76, 'GB' => 77,
|
||||
'GD' => 78, 'GE' => 79, 'GF' => 80, 'GH' => 81, 'GI' => 82, 'GL' => 83,
|
||||
'GM' => 84, 'GN' => 85, 'GP' => 86, 'GQ' => 87, 'GR' => 88, 'GS' => 89,
|
||||
'GT' => 90, 'GU' => 91, 'GW' => 92, 'GY' => 93, 'HK' => 94, 'HM' => 95,
|
||||
'HN' => 96, 'HR' => 97, 'HT' => 98, 'HU' => 99, 'ID' => 100,
|
||||
'IE' => 101, 'IL' => 102, 'IN' => 103, 'IO' => 104, 'IQ' => 105,
|
||||
'IR' => 106, 'IS' => 107, 'IT' => 108, 'JM' => 109, 'JO' => 110,
|
||||
'JP' => 111, 'KE' => 112, 'KG' => 113, 'KH' => 114, 'KI' => 115,
|
||||
'KM' => 116, 'KN' => 117, 'KP' => 118, 'KR' => 119, 'KW' => 120,
|
||||
'KY' => 121, 'KZ' => 122, 'LA' => 123, 'LB' => 124, 'LC' => 125,
|
||||
'LI' => 126, 'LK' => 127, 'LR' => 128, 'LS' => 129, 'LT' => 130,
|
||||
'LU' => 131, 'LV' => 132, 'LY' => 133, 'MA' => 134, 'MC' => 135,
|
||||
'MD' => 136, 'MG' => 137, 'MH' => 138, 'MK' => 139, 'ML' => 140,
|
||||
'MM' => 141, 'MN' => 142, 'MO' => 143, 'MP' => 144, 'MQ' => 145,
|
||||
'MR' => 146, 'MS' => 147, 'MT' => 148, 'MU' => 149, 'MV' => 150,
|
||||
'MW' => 151, 'MX' => 152, 'MY' => 153, 'MZ' => 154, 'NA' => 155,
|
||||
'NC' => 156, 'NE' => 157, 'NF' => 158, 'NG' => 159, 'NI' => 160,
|
||||
'NL' => 161, 'NO' => 162, 'NP' => 163, 'NR' => 164, 'NU' => 165,
|
||||
'NZ' => 166, 'OM' => 167, 'PA' => 168, 'PE' => 169, 'PF' => 170,
|
||||
'PG' => 171, 'PH' => 172, 'PK' => 173, 'PL' => 174, 'PM' => 175,
|
||||
'PN' => 176, 'PR' => 177, 'PS' => 178, 'PT' => 179, 'PW' => 180,
|
||||
'PY' => 181, 'QA' => 182, 'RE' => 183, 'RO' => 184, 'RU' => 185,
|
||||
'RW' => 186, 'SA' => 187, 'SB' => 188, 'SC' => 189, 'SD' => 190,
|
||||
'SE' => 191, 'SG' => 192, 'SH' => 193, 'SI' => 194, 'SJ' => 195,
|
||||
'SK' => 196, 'SL' => 197, 'SM' => 198, 'SN' => 199, 'SO' => 200,
|
||||
'SR' => 201, 'ST' => 202, 'SV' => 203, 'SY' => 204, 'SZ' => 205,
|
||||
'TC' => 206, 'TD' => 207, 'TF' => 208, 'TG' => 209, 'TH' => 210,
|
||||
'TJ' => 211, 'TK' => 212, 'TM' => 213, 'TN' => 214, 'TO' => 215,
|
||||
'TL' => 216, 'TR' => 217, 'TT' => 218, 'TV' => 219, 'TW' => 220,
|
||||
'TZ' => 221, 'UA' => 222, 'UG' => 223, 'UM' => 224, 'US' => 225,
|
||||
'UY' => 226, 'UZ' => 227, 'VA' => 228, 'VC' => 229, 'VE' => 230,
|
||||
'VG' => 231, 'VI' => 232, 'VN' => 233, 'VU' => 234, 'WF' => 235,
|
||||
'WS' => 236, 'YE' => 237, 'YT' => 238, 'RS' => 239, 'ZA' => 240,
|
||||
'ZM' => 241, 'ME' => 242, 'ZW' => 243, 'A1' => 244, 'A2' => 245,
|
||||
'O1' => 246, 'AX' => 247, 'GG' => 248, 'IM' => 249, 'JE' => 250);
|
||||
|
||||
var $GEOIP_COUNTRY_CODES = array(
|
||||
'', 'AP', 'EU', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO',
|
||||
'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF',
|
||||
'BG', 'BH', 'BI', 'BJ', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT', 'BV', 'BW',
|
||||
'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM',
|
||||
'CN', 'CO', 'CR', 'CU', 'CV', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM',
|
||||
'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK',
|
||||
'FM', 'FO', 'FR', 'FX', 'GA', 'GB', 'GD', 'GE', 'GF', 'GH', 'GI', 'GL',
|
||||
'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM',
|
||||
'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN', 'IO', 'IQ', 'IR', 'IS',
|
||||
'IT', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR',
|
||||
'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU',
|
||||
'LV', 'LY', 'MA', 'MC', 'MD', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO',
|
||||
'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA',
|
||||
'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM',
|
||||
'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT',
|
||||
'PW', 'PY', 'QA', 'RE', 'RO', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE',
|
||||
'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'ST', 'SV',
|
||||
'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TM', 'TN', 'TO',
|
||||
'TL', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ',
|
||||
'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'RS',
|
||||
'ZA', 'ZM', 'ME', 'ZW', 'A1', 'A2', 'O1', 'AX', 'GG', 'IM', 'JE');
|
||||
|
||||
var $GEOIP_COUNTRY_CODES3 = array(
|
||||
'','AP','EU','AND','ARE','AFG','ATG','AIA','ALB','ARM','ANT','AGO',
|
||||
'AQ','ARG','ASM','AUT','AUS','ABW','AZE','BIH','BRB','BGD','BEL','BFA',
|
||||
'BGR','BHR','BDI','BEN','BMU','BRN','BOL','BRA','BHS','BTN','BV','BWA',
|
||||
'BLR','BLZ','CAN','CC','COD','CAF','COG','CHE','CIV','COK','CHL','CMR',
|
||||
'CHN','COL','CRI','CUB','CPV','CX','CYP','CZE','DEU','DJI','DNK','DMA',
|
||||
'DOM','DZA','ECU','EST','EGY','ESH','ERI','ESP','ETH','FIN','FJI',
|
||||
'FLK','FSM','FRO','FRA','FX','GAB','GBR','GRD','GEO','GUF','GHA','GIB',
|
||||
'GRL','GMB','GIN','GLP','GNQ','GRC','GS','GTM','GUM','GNB','GUY','HKG',
|
||||
'HM','HND','HRV','HTI','HUN','IDN','IRL','ISR','IND','IO','IRQ','IRN',
|
||||
'ISL','ITA','JAM','JOR','JPN','KEN','KGZ','KHM','KIR','COM','KNA',
|
||||
'PRK','KOR','KWT','CYM','KAZ','LAO','LBN','LCA','LIE','LKA','LBR',
|
||||
'LSO','LTU','LUX','LVA','LBY','MAR','MCO','MDA','MDG','MHL','MKD',
|
||||
'MLI','MMR','MNG','MAC','MNP','MTQ','MRT','MSR','MLT','MUS','MDV',
|
||||
'MWI','MEX','MYS','MOZ','NAM','NCL','NER','NFK','NGA','NIC','NLD',
|
||||
'NOR','NPL','NRU','NIU','NZL','OMN','PAN','PER','PYF','PNG','PHL',
|
||||
'PAK','POL','SPM','PCN','PRI','PSE','PRT','PLW','PRY','QAT','REU',
|
||||
'ROU','RUS','RWA','SAU','SLB','SYC','SDN','SWE','SGP','SHN','SVN',
|
||||
'SJM','SVK','SLE','SMR','SEN','SOM','SUR','STP','SLV','SYR','SWZ',
|
||||
'TCA','TCD','TF','TGO','THA','TJK','TKL','TLS','TKM','TUN','TON','TUR',
|
||||
'TTO','TUV','TWN','TZA','UKR','UGA','UM','USA','URY','UZB','VAT','VCT',
|
||||
'VEN','VGB','VIR','VNM','VUT','WLF','WSM','YEM','YT','SRB','ZAF','ZMB',
|
||||
'MNE','ZWE','A1','A2','O1','ALA','GGY','IMN','JEY');
|
||||
|
||||
var $GEOIP_COUNTRY_NAMES = array(
|
||||
'', 'Asia/Pacific Region', 'Europe', 'Andorra', 'United Arab Emirates',
|
||||
'Afghanistan', 'Antigua and Barbuda', 'Anguilla', 'Albania', 'Armenia',
|
||||
'Netherlands Antilles', 'Angola', 'Antarctica', 'Argentina',
|
||||
'American Samoa', 'Austria', 'Australia', 'Aruba', 'Azerbaijan',
|
||||
'Bosnia and Herzegovina', 'Barbados', 'Bangladesh', 'Belgium',
|
||||
'Burkina Faso', 'Bulgaria', 'Bahrain', 'Burundi', 'Benin', 'Bermuda',
|
||||
'Brunei Darussalam', 'Bolivia', 'Brazil', 'Bahamas', 'Bhutan',
|
||||
'Bouvet Island', 'Botswana', 'Belarus', 'Belize',
|
||||
'Canada', 'Cocos (Keeling) Islands',
|
||||
'Congo, The Democratic Republic of the',
|
||||
'Central African Republic', 'Congo', 'Switzerland', 'Cote D\'Ivoire',
|
||||
'Cook Islands', 'Chile', 'Cameroon', 'China', 'Colombia', 'Costa Rica',
|
||||
'Cuba', 'Cape Verde', 'Christmas Island', 'Cyprus', 'Czech Republic',
|
||||
'Germany', 'Djibouti', 'Denmark', 'Dominica', 'Dominican Republic',
|
||||
'Algeria', 'Ecuador', 'Estonia',
|
||||
'Egypt', 'Western Sahara', 'Eritrea', 'Spain', 'Ethiopia', 'Finland',
|
||||
'Fiji', 'Falkland Islands (Malvinas)',
|
||||
'Micronesia, Federated States of', 'Faroe Islands', 'France',
|
||||
'France, Metropolitan', 'Gabon', 'United Kingdom',
|
||||
'Grenada', 'Georgia', 'French Guiana', 'Ghana', 'Gibraltar',
|
||||
'Greenland', 'Gambia', 'Guinea', 'Guadeloupe', 'Equatorial Guinea',
|
||||
'Greece', 'South Georgia and the South Sandwich Islands', 'Guatemala',
|
||||
'Guam', 'Guinea-Bissau',
|
||||
'Guyana', 'Hong Kong', 'Heard Island and McDonald Islands', 'Honduras',
|
||||
'Croatia', 'Haiti', 'Hungary', 'Indonesia', 'Ireland', 'Israel',
|
||||
'India', 'British Indian Ocean Territory', 'Iraq',
|
||||
'Iran, Islamic Republic of',
|
||||
'Iceland', 'Italy', 'Jamaica', 'Jordan', 'Japan', 'Kenya', 'Kyrgyzstan',
|
||||
'Cambodia', 'Kiribati', 'Comoros', 'Saint Kitts and Nevis',
|
||||
'Korea, Democratic People\'s Republic of',
|
||||
'Korea, Republic of', 'Kuwait', 'Cayman Islands',
|
||||
'Kazakstan', 'Lao People\'s Democratic Republic', 'Lebanon',
|
||||
'Saint Lucia', 'Liechtenstein', 'Sri Lanka', 'Liberia', 'Lesotho',
|
||||
'Lithuania', 'Luxembourg',
|
||||
'Latvia', 'Libyan Arab Jamahiriya', 'Morocco', 'Monaco',
|
||||
'Moldova, Republic of', 'Madagascar', 'Marshall Islands', 'Macedonia',
|
||||
'Mali', 'Myanmar', 'Mongolia', 'Macau', 'Northern Mariana Islands',
|
||||
'Martinique', 'Mauritania', 'Montserrat', 'Malta', 'Mauritius',
|
||||
'Maldives', 'Malawi', 'Mexico', 'Malaysia', 'Mozambique', 'Namibia',
|
||||
'New Caledonia', 'Niger', 'Norfolk Island', 'Nigeria', 'Nicaragua',
|
||||
'Netherlands', 'Norway', 'Nepal', 'Nauru', 'Niue', 'New Zealand',
|
||||
'Oman', 'Panama', 'Peru', 'French Polynesia', 'Papua New Guinea',
|
||||
'Philippines', 'Pakistan', 'Poland', 'Saint Pierre and Miquelon',
|
||||
'Pitcairn Islands', 'Puerto Rico', 'Palestinian Territory',
|
||||
'Portugal', 'Palau', 'Paraguay', 'Qatar', 'Reunion', 'Romania',
|
||||
'Russian Federation', 'Rwanda', 'Saudi Arabia', 'Solomon Islands',
|
||||
'Seychelles', 'Sudan', 'Sweden', 'Singapore', 'Saint Helena',
|
||||
'Slovenia', 'Svalbard and Jan Mayen', 'Slovakia', 'Sierra Leone',
|
||||
'San Marino', 'Senegal', 'Somalia', 'Suriname',
|
||||
'Sao Tome and Principe', 'El Salvador', 'Syrian Arab Republic',
|
||||
'Swaziland', 'Turks and Caicos Islands', 'Chad',
|
||||
'French Southern Territories', 'Togo', 'Thailand', 'Tajikistan',
|
||||
'Tokelau', 'Turkmenistan', 'Tunisia', 'Tonga', 'Timor-Leste', 'Turkey',
|
||||
'Trinidad and Tobago', 'Tuvalu', 'Taiwan',
|
||||
'Tanzania, United Republic of', 'Ukraine',
|
||||
'Uganda', 'United States Minor Outlying Islands', 'United States',
|
||||
'Uruguay','Uzbekistan', 'Holy See (Vatican City State)',
|
||||
'Saint Vincent and the Grenadines', 'Venezuela',
|
||||
'Virgin Islands, British', 'Virgin Islands, U.S.',
|
||||
'Vietnam', 'Vanuatu', 'Wallis and Futuna', 'Samoa', 'Yemen', 'Mayotte',
|
||||
'Serbia', 'South Africa', 'Zambia', 'Montenegro', 'Zimbabwe',
|
||||
'Anonymous Proxy','Satellite Provider','Other',
|
||||
'Aland Islands','Guernsey','Isle of Man','Jersey');
|
||||
}
|
||||
|
||||
function GeoIP_load_shared_mem ($file) {
|
||||
|
||||
$fp = fopen($file, 'rb');
|
||||
if (!$fp) {
|
||||
print "error opening $file: $php_errormsg\n";
|
||||
exit;
|
||||
}
|
||||
$s_array = fstat($fp);
|
||||
$size = $s_array['size'];
|
||||
if ($shmid = @shmop_open (GEOIP_SHM_KEY, "w", 0, 0)) {
|
||||
shmop_delete ($shmid);
|
||||
shmop_close ($shmid);
|
||||
}
|
||||
$shmid = shmop_open (GEOIP_SHM_KEY, "c", 0644, $size);
|
||||
shmop_write ($shmid, fread($fp, $size), 0);
|
||||
shmop_close ($shmid);
|
||||
}
|
||||
|
||||
function _setup_segments($gi){
|
||||
$gi->databaseType = GEOIP_COUNTRY_EDITION;
|
||||
$gi->record_length = STANDARD_RECORD_LENGTH;
|
||||
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
||||
$offset = @shmop_size ($gi->shmid) - 3;
|
||||
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
|
||||
$delim = @shmop_read ($gi->shmid, $offset, 3);
|
||||
$offset += 3;
|
||||
if ($delim == (chr(255).chr(255).chr(255))) {
|
||||
$gi->databaseType = ord(@shmop_read ($gi->shmid, $offset, 1));
|
||||
$offset++;
|
||||
|
||||
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
|
||||
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
|
||||
} else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
|
||||
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
|
||||
} else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)||
|
||||
($gi->databaseType == GEOIP_CITY_EDITION_REV1)
|
||||
|| ($gi->databaseType == GEOIP_ORG_EDITION)
|
||||
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|
||||
|| ($gi->databaseType == GEOIP_ASNUM_EDITION)){
|
||||
$gi->databaseSegments = 0;
|
||||
$buf = @shmop_read ($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
|
||||
for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
|
||||
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
|
||||
}
|
||||
if (($gi->databaseType == GEOIP_ORG_EDITION)||
|
||||
($gi->databaseType == GEOIP_ISP_EDITION)) {
|
||||
$gi->record_length = ORG_RECORD_LENGTH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
$offset -= 4;
|
||||
}
|
||||
}
|
||||
if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
|
||||
($gi->databaseType == GEOIP_PROXY_EDITION)||
|
||||
($gi->databaseType == GEOIP_NETSPEED_EDITION)){
|
||||
$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
|
||||
}
|
||||
} else {
|
||||
$filepos = ftell($gi->filehandle);
|
||||
fseek($gi->filehandle, -3, SEEK_END);
|
||||
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
|
||||
$delim = fread($gi->filehandle,3);
|
||||
if ($delim == (chr(255).chr(255).chr(255))){
|
||||
$gi->databaseType = ord(fread($gi->filehandle,1));
|
||||
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
|
||||
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
|
||||
}
|
||||
else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
|
||||
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
|
||||
} else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0) ||
|
||||
($gi->databaseType == GEOIP_CITY_EDITION_REV1) ||
|
||||
($gi->databaseType == GEOIP_ORG_EDITION) ||
|
||||
($gi->databaseType == GEOIP_ISP_EDITION) ||
|
||||
($gi->databaseType == GEOIP_ASNUM_EDITION)){
|
||||
$gi->databaseSegments = 0;
|
||||
$buf = fread($gi->filehandle,SEGMENT_RECORD_LENGTH);
|
||||
for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
|
||||
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
|
||||
}
|
||||
if ($gi->databaseType == GEOIP_ORG_EDITION ||
|
||||
$gi->databaseType == GEOIP_ISP_EDITION) {
|
||||
$gi->record_length = ORG_RECORD_LENGTH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
fseek($gi->filehandle, -4, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
|
||||
($gi->databaseType == GEOIP_PROXY_EDITION)||
|
||||
($gi->databaseType == GEOIP_NETSPEED_EDITION)){
|
||||
$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
|
||||
}
|
||||
fseek($gi->filehandle,$filepos,SEEK_SET);
|
||||
}
|
||||
return $gi;
|
||||
}
|
||||
|
||||
function GeoIP_open($filename, $flags) {
|
||||
$gi = new GeoIP;
|
||||
$gi->flags = $flags;
|
||||
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
||||
$gi->shmid = @shmop_open (GEOIP_SHM_KEY, "a", 0, 0);
|
||||
} else {
|
||||
$gi->filehandle = fopen($filename,"rb");
|
||||
if ($gi->flags & GEOIP_MEMORY_CACHE) {
|
||||
$s_array = fstat($gi->filehandle);
|
||||
$gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
|
||||
}
|
||||
}
|
||||
|
||||
$gi = _setup_segments($gi);
|
||||
return $gi;
|
||||
}
|
||||
|
||||
function GeoIP_close($gi) {
|
||||
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return fclose($gi->filehandle);
|
||||
}
|
||||
|
||||
function GeoIP_country_id_by_name($gi, $name) {
|
||||
$addr = gethostbyname($name);
|
||||
if (!$addr || $addr == $name) {
|
||||
return false;
|
||||
}
|
||||
return GeoIP_country_id_by_addr($gi, $addr);
|
||||
}
|
||||
|
||||
function GeoIP_country_code_by_name($gi, $name) {
|
||||
$country_id = GeoIP_country_id_by_name($gi,$name);
|
||||
if ($country_id !== false) {
|
||||
return $gi->GEOIP_COUNTRY_CODES[$country_id];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function GeoIP_country_name_by_name($gi, $name) {
|
||||
$country_id = GeoIP_country_id_by_name($gi,$name);
|
||||
if ($country_id !== false) {
|
||||
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function GeoIP_country_id_by_addr($gi, $addr) {
|
||||
$ipnum = ip2long($addr);
|
||||
return _GeoIP_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
|
||||
}
|
||||
|
||||
function GeoIP_country_code_by_addr($gi, $addr) {
|
||||
if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
|
||||
$record = GeoIP_record_by_addr($gi,$addr);
|
||||
return $record->country_code;
|
||||
} else {
|
||||
$country_id = GeoIP_country_id_by_addr($gi,$addr);
|
||||
if ($country_id !== false) {
|
||||
return $gi->GEOIP_COUNTRY_CODES[$country_id];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function GeoIP_country_name_by_addr($gi, $addr) {
|
||||
if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
|
||||
$record = GeoIP_record_by_addr($gi,$addr);
|
||||
return $record->country_name;
|
||||
} else {
|
||||
$country_id = GeoIP_country_id_by_addr($gi,$addr);
|
||||
if ($country_id !== false) {
|
||||
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function _GeoIP_seek_country($gi, $ipnum) {
|
||||
$offset = 0;
|
||||
for ($depth = 31; $depth >= 0; --$depth) {
|
||||
if ($gi->flags & GEOIP_MEMORY_CACHE) {
|
||||
$buf = substr($gi->memory_buffer,
|
||||
2 * $gi->record_length * $offset,
|
||||
2 * $gi->record_length);
|
||||
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
|
||||
$buf = @shmop_read ($gi->shmid,
|
||||
2 * $gi->record_length * $offset,
|
||||
2 * $gi->record_length );
|
||||
} else {
|
||||
fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
|
||||
or die("fseek failed");
|
||||
$buf = fread($gi->filehandle, 2 * $gi->record_length);
|
||||
}
|
||||
$x = array(0,0);
|
||||
for ($i = 0; $i < 2; ++$i) {
|
||||
for ($j = 0; $j < $gi->record_length; ++$j) {
|
||||
$x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
|
||||
}
|
||||
}
|
||||
if ($ipnum & (1 << $depth)) {
|
||||
if ($x[1] >= $gi->databaseSegments) {
|
||||
return $x[1];
|
||||
}
|
||||
$offset = $x[1];
|
||||
} else {
|
||||
if ($x[0] >= $gi->databaseSegments) {
|
||||
return $x[0];
|
||||
}
|
||||
$offset = $x[0];
|
||||
}
|
||||
}
|
||||
trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
function _get_org($gi,$ipnum){
|
||||
$seek_org = _GeoIP_seek_country($gi,$ipnum);
|
||||
if ($seek_org == $gi->databaseSegments) {
|
||||
return NULL;
|
||||
}
|
||||
$record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
|
||||
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
||||
$org_buf = @shmop_read ($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
|
||||
} else {
|
||||
fseek($gi->filehandle, $record_pointer, SEEK_SET);
|
||||
$org_buf = fread($gi->filehandle,MAX_ORG_RECORD_LENGTH);
|
||||
}
|
||||
$org_buf = substr($org_buf, 0, strpos($org_buf, 0));
|
||||
return $org_buf;
|
||||
}
|
||||
|
||||
function GeoIP_org_by_addr ($gi,$addr) {
|
||||
if ($addr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
$ipnum = ip2long($addr);
|
||||
return _get_org($gi, $ipnum);
|
||||
}
|
||||
|
||||
function _get_region($gi,$ipnum){
|
||||
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
|
||||
$seek_region = _GeoIP_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV0;
|
||||
if ($seek_region >= 1000){
|
||||
$country_code = "US";
|
||||
$region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
|
||||
} else {
|
||||
$country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
|
||||
$region = "";
|
||||
}
|
||||
return array ($country_code,$region);
|
||||
} else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
|
||||
$seek_region = _GeoIP_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV1;
|
||||
//print $seek_region;
|
||||
if ($seek_region < US_OFFSET){
|
||||
$country_code = "";
|
||||
$region = "";
|
||||
} else if ($seek_region < CANADA_OFFSET) {
|
||||
$country_code = "US";
|
||||
$region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65);
|
||||
} else if ($seek_region < WORLD_OFFSET) {
|
||||
$country_code = "CA";
|
||||
$region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65);
|
||||
} else {
|
||||
$country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
|
||||
$region = "";
|
||||
}
|
||||
return array ($country_code,$region);
|
||||
}
|
||||
}
|
||||
|
||||
function GeoIP_region_by_addr ($gi,$addr) {
|
||||
if ($addr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
$ipnum = ip2long($addr);
|
||||
return _get_region($gi, $ipnum);
|
||||
}
|
||||
|
||||
function GeoIP_getdnsattributes ($l,$ip){
|
||||
$r = new Net_DNS_Resolver();
|
||||
$r->nameservers = array("ws1.maxmind.com");
|
||||
$p = $r->search($l."." . $ip .".s.maxmind.com","TXT","IN");
|
||||
$str = is_object($p->answer[0])?$p->answer[0]->string():'';
|
||||
ereg("\"(.*)\"",$str,$regs);
|
||||
$str = $regs[1];
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 2 character code of the country given the request object.
|
||||
*
|
||||
* @param Pluf_HTTP_Request
|
||||
* @param string Path to the GeoIP database
|
||||
* @return string 2 character ISO code
|
||||
*/
|
||||
function GeoIP_countryOfRequest($request, $geoipdb)
|
||||
{
|
||||
$gi = GeoIP_open($geoipdb, GEOIP_STANDARD);
|
||||
$code = GeoIP_country_code_by_addr($gi, $request->remote_addr);
|
||||
GeoIP_close($gi);
|
||||
return ($code != false) ? $code : 'ZZ';
|
||||
}
|
439
pluf/src/Pluf.php
Normal file
439
pluf/src/Pluf.php
Normal file
@@ -0,0 +1,439 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The main class of the framework. From where all start.
|
||||
*
|
||||
* The __autoload function is automatically set.
|
||||
*/
|
||||
class Pluf
|
||||
{
|
||||
/**
|
||||
* Start the Plume Framework.
|
||||
*
|
||||
* Load the configuration files.
|
||||
*
|
||||
* @param string Configuration file to use
|
||||
*/
|
||||
static function start($config)
|
||||
{
|
||||
$GLOBALS['_PX_starttime'] = microtime(true);
|
||||
$GLOBALS['_PX_uniqid'] = uniqid($GLOBALS['_PX_starttime'], true);
|
||||
$GLOBALS['_PX_signal'] = array();
|
||||
$GLOBALS['_PX_locale'] = array();
|
||||
Pluf::loadConfig($config);
|
||||
date_default_timezone_set(Pluf::f('time_zone', 'Europe/Berlin'));
|
||||
mb_internal_encoding(Pluf::f('encoding', 'UTF-8'));
|
||||
mb_regex_encoding(Pluf::f('encoding', 'UTF-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given configuration file.
|
||||
*
|
||||
* The configuration is saved in the $GLOBALS['_PX_config'] array.
|
||||
* The relations between the models are loaded in $GLOBALS['_PX_models'].
|
||||
*
|
||||
* @param string Configuration file to load.
|
||||
*/
|
||||
static function loadConfig($config_file)
|
||||
{
|
||||
if (false !== ($file=Pluf::fileExists($config_file))) {
|
||||
$GLOBALS['_PX_config'] = require $file;
|
||||
} else {
|
||||
throw new Exception('Configuration file does not exist: '.$config_file);
|
||||
}
|
||||
// Load the relations for each installed application. Each
|
||||
// application folder must be in the include path.
|
||||
self::loadRelations(!Pluf::f('debug', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model relations and signals.
|
||||
*
|
||||
* If not in debug mode, it will automatically cache the
|
||||
* information. This allows one include file when many
|
||||
* applications and thus many includes are needed.
|
||||
*
|
||||
* Signals and relations are cached in the same file as the way to
|
||||
* go for signals is to put them in the relations.php file.
|
||||
*
|
||||
* @param bool Use the cache (true)
|
||||
*/
|
||||
static function loadRelations($usecache=true)
|
||||
{
|
||||
$GLOBALS['_PX_models'] = array();
|
||||
$GLOBALS['_PX_models_init_cache'] = array();
|
||||
$apps = Pluf::f('installed_apps', array());
|
||||
$cache = Pluf::f('tmp_folder').'/Pluf_relations_cache_'.md5(serialize($apps)).'.phps';
|
||||
if ($usecache and file_exists($cache)) {
|
||||
list($GLOBALS['_PX_models'],
|
||||
$GLOBALS['_PX_models_related'],
|
||||
$GLOBALS['_PX_signal']) = include $cache;
|
||||
return;
|
||||
}
|
||||
$m = $GLOBALS['_PX_models'];
|
||||
foreach ($apps as $app) {
|
||||
$m = array_merge_recursive($m, require $app.'/relations.php');
|
||||
}
|
||||
$GLOBALS['_PX_models'] = $m;
|
||||
|
||||
$_r = array(
|
||||
'relate_to' => array(),
|
||||
'relate_to_many' => array(),
|
||||
);
|
||||
foreach ($GLOBALS['_PX_models'] as $model => $relations) {
|
||||
foreach ($relations as $type => $related) {
|
||||
foreach ($related as $related_model) {
|
||||
if (!isset($_r[$type][$related_model])) {
|
||||
$_r[$type][$related_model] = array();
|
||||
}
|
||||
$_r[$type][$related_model][] = $model;
|
||||
}
|
||||
}
|
||||
}
|
||||
$_r['foreignkey'] = $_r['relate_to'];
|
||||
$_r['manytomany'] = $_r['relate_to_many'];
|
||||
$GLOBALS['_PX_models_related'] = $_r;
|
||||
|
||||
// $GLOBALS['_PX_signal'] is automatically set by the require
|
||||
// statement and possibly in the configuration file.
|
||||
if ($usecache) {
|
||||
$s = var_export(array($GLOBALS['_PX_models'],
|
||||
$GLOBALS['_PX_models_related'],
|
||||
$GLOBALS['_PX_signal']), true);
|
||||
if (@file_put_contents($cache, '<?php return '.$s.';'."\n",
|
||||
LOCK_EX)) {
|
||||
chmod($cache, 0755);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access a configuration variable.
|
||||
*
|
||||
* @param string Configuration variable
|
||||
* @param mixed Possible default value if value is not set ('')
|
||||
* @return mixed Configuration variable or default value if not defined.
|
||||
*/
|
||||
static function f($cfg, $default='')
|
||||
{
|
||||
if (isset($GLOBALS['_PX_config'][$cfg])) {
|
||||
return $GLOBALS['_PX_config'][$cfg];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access an array of configuration variables having a given
|
||||
* prefix.
|
||||
*
|
||||
* @param string Prefix.
|
||||
* @param bool Strip the prefix from the keys (false).
|
||||
* @return array Configuration variables.
|
||||
*/
|
||||
static function pf($pfx, $strip=false)
|
||||
{
|
||||
$ret = array();
|
||||
$pfx_len = strlen($pfx);
|
||||
foreach ($GLOBALS['_PX_config'] as $key=>$val) {
|
||||
if (0 === strpos($key, $pfx)) {
|
||||
if (!$strip) {
|
||||
$ret[$key] = $val;
|
||||
} else {
|
||||
$ret[substr($key, $pfx_len)] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a given object.
|
||||
*
|
||||
* Loads automatically the corresponding class file if needed.
|
||||
* If impossible to get the class $model, exception is thrown.
|
||||
*
|
||||
* @param string Model to load.
|
||||
* @param mixed Extra parameters for the constructor of the model.
|
||||
*/
|
||||
public static function factory($model, $params=null)
|
||||
{
|
||||
if ($params !== null) {
|
||||
return new $model($params);
|
||||
}
|
||||
return new $model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class depending on its name.
|
||||
*
|
||||
* Throw an exception if not possible to load the class.
|
||||
*
|
||||
* @param string Class to load.
|
||||
*/
|
||||
public static function loadClass($class)
|
||||
{
|
||||
if (class_exists($class, false)) {
|
||||
return;
|
||||
}
|
||||
$file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
|
||||
include $file;
|
||||
if (!class_exists($class, false)) {
|
||||
$error = 'Impossible to load the class: '.$class."\n".
|
||||
'Tried to include: '.$file."\n".
|
||||
'Include path: '.get_include_path();
|
||||
throw new Exception($error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a function depending on its name.
|
||||
*
|
||||
* The implementation file of the function
|
||||
* MyApp_Youpla_Boum_Stuff() is MyApp/Youpla/Boum.php That way it
|
||||
* is possible to group all the related function in one file.
|
||||
*
|
||||
* Throw an exception if not possible to load the function.
|
||||
*
|
||||
* @param string Function to load.
|
||||
*/
|
||||
public static function loadFunction($function)
|
||||
{
|
||||
if (function_exists($function)) {
|
||||
return;
|
||||
}
|
||||
$elts = explode('_', $function);
|
||||
array_pop($elts);
|
||||
$file = implode(DIRECTORY_SEPARATOR, $elts) . '.php';
|
||||
if (false !== ($file=Pluf::fileExists($file))) {
|
||||
include $file;
|
||||
}
|
||||
if (!function_exists($function)) {
|
||||
throw new Exception('Impossible to load the function: '.$function);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hack for [[php file_exists()]] that checks the include_path.
|
||||
*
|
||||
* Use this to see if a file exists anywhere in the include_path.
|
||||
*
|
||||
* <code type="php">
|
||||
* $file = 'path/to/file.php';
|
||||
* if (Pluf::fileExists('path/to/file.php')) {
|
||||
* include $file;
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @credits Paul M. Jones <pmjones@solarphp.net>
|
||||
*
|
||||
* @param string $file Check for this file in the include_path.
|
||||
* @return mixed Full path to the file if the file exists and
|
||||
* is readable in the include_path, false if not.
|
||||
*/
|
||||
public static function fileExists($file)
|
||||
{
|
||||
$file = trim($file);
|
||||
if (!$file) {
|
||||
return false;
|
||||
}
|
||||
// using an absolute path for the file?
|
||||
// dual check for Unix '/' and Windows '\',
|
||||
// or Windows drive letter and a ':'.
|
||||
$abs = ($file[0] == '/' || $file[0] == '\\' || $file[1] == ':');
|
||||
if ($abs && file_exists($file)) {
|
||||
return $file;
|
||||
}
|
||||
// using a relative path on the file
|
||||
$path = explode(PATH_SEPARATOR, ini_get('include_path'));
|
||||
foreach ($path as $dir) {
|
||||
// strip Unix '/' and Windows '\'
|
||||
$target = rtrim($dir, '\\/').DIRECTORY_SEPARATOR.$file;
|
||||
if (file_exists($target)) {
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
// never found it
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to load the default database connection.
|
||||
*
|
||||
* This method is just dispatching to the function define in the
|
||||
* configuration by the 'db_get_connection' key or use the default
|
||||
* 'Pluf_DB_getConnection'. If you want to use your own function,
|
||||
* take a look at the Pluf_DB_getConnection function to use the
|
||||
* same approach for your method.
|
||||
*
|
||||
* The extra parameters can be used to selectively connect to a
|
||||
* given database. When the ORM is getting a connection, it is
|
||||
* passing the current model as parameter. That way you could get
|
||||
* different databases for different models.
|
||||
*
|
||||
* @param mixed Extra parameters.
|
||||
* @return resource DB connection.
|
||||
*/
|
||||
public static function &db($extra=null)
|
||||
{
|
||||
$func = Pluf::f('db_get_connection', 'Pluf_DB_getConnection');
|
||||
Pluf::loadFunction($func);
|
||||
$a = $func($extra);
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Translate a string.
|
||||
*
|
||||
* @param string String to be translated.
|
||||
* @return string Translated string.
|
||||
*/
|
||||
function __($str)
|
||||
{
|
||||
$locale = (isset($GLOBALS['_PX_current_locale'])) ? $GLOBALS['_PX_current_locale'] : 'en';
|
||||
if (!empty($GLOBALS['_PX_locale'][$locale][$str][0])) {
|
||||
return $GLOBALS['_PX_locale'][$locale][$str][0];
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the plural form of a string.
|
||||
*
|
||||
* @param string Singular form of the string.
|
||||
* @param string Plural form of the string.
|
||||
* @param int Number of elements.
|
||||
* @return string Translated string.
|
||||
*/
|
||||
function _n($sing, $plur, $n)
|
||||
{
|
||||
$locale = (isset($GLOBALS['_PX_current_locale'])) ? $GLOBALS['_PX_current_locale'] : 'en';
|
||||
if (isset($GLOBALS['_PX_current_locale_plural_form'])) {
|
||||
$pform = $GLOBALS['_PX_current_locale_plural_form'];
|
||||
} else {
|
||||
$pform = Pluf_Translation::getPluralForm($locale);
|
||||
}
|
||||
$index = Pluf_Translation::$pform($n);
|
||||
if (!empty($GLOBALS['_PX_locale'][$locale][$sing.'#'.$plur][$index])) {
|
||||
return $GLOBALS['_PX_locale'][$locale][$sing.'#'.$plur][$index];
|
||||
}
|
||||
// We have no translations or default English
|
||||
if ($n == 1) {
|
||||
return $sing;
|
||||
}
|
||||
return $plur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autoload function.
|
||||
*
|
||||
* @param string Class name.
|
||||
*/
|
||||
function __autoload($class_name)
|
||||
{
|
||||
try {
|
||||
Pluf::loadClass($class_name);
|
||||
} catch (Exception $e) {
|
||||
if (Pluf::f('debug')) {
|
||||
print $e->getMessage();
|
||||
die();
|
||||
}
|
||||
eval("class $class_name {
|
||||
function __construct() {
|
||||
throw new Exception('Class $class_name not found');
|
||||
}
|
||||
|
||||
static function __callstatic(\$m, \$args) {
|
||||
throw new Exception('Class $class_name not found');
|
||||
}
|
||||
}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception to catch the PHP errors.
|
||||
*
|
||||
* @credits errd
|
||||
* @see http://www.php.net/manual/en/function.set-error-handler.php
|
||||
*/
|
||||
class PlufErrorHandlerException extends Exception
|
||||
{
|
||||
public function setLine($line)
|
||||
{
|
||||
$this->line = $line;
|
||||
}
|
||||
|
||||
public function setFile($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that is the real error handler.
|
||||
*/
|
||||
function PlufErrorHandler($code, $string, $file, $line)
|
||||
{
|
||||
if (0 == error_reporting()) return false;
|
||||
if (E_STRICT == $code
|
||||
&&
|
||||
(
|
||||
0 === strpos($file, Pluf::f('pear_path','/usr/share/php/'))
|
||||
or
|
||||
false !== strripos($file, 'pear') // if pear in the path, ignore
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
$exception = new PlufErrorHandlerException($string, $code);
|
||||
$exception->setLine($line);
|
||||
$exception->setFile($file);
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
// Set the error handler only if not performing the unittests.
|
||||
if (!defined('IN_UNIT_TESTS')) {
|
||||
set_error_handler('PlufErrorHandler', error_reporting());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shortcut needed all over the place.
|
||||
*
|
||||
* Note that in some cases, we need to escape strings not in UTF-8, so
|
||||
* this is not possible to safely use a call to htmlspecialchars. This
|
||||
* is why str_replace is used.
|
||||
*
|
||||
* @param string Raw string
|
||||
* @return string HTML escaped string
|
||||
*/
|
||||
function Pluf_esc($string)
|
||||
{
|
||||
return str_replace(array('&', '"', '<', '>'),
|
||||
array('&', '"', '<', '>'),
|
||||
(string) $string);
|
||||
}
|
1
pluf/src/Pluf/.htaccess
Normal file
1
pluf/src/Pluf/.htaccess
Normal file
@@ -0,0 +1 @@
|
||||
Deny from all
|
556
pluf/src/Pluf/AB.php
Normal file
556
pluf/src/Pluf/AB.php
Normal file
@@ -0,0 +1,556 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Core A/B testing component.
|
||||
*
|
||||
* The two importants methods are `test` and `convert`.
|
||||
*
|
||||
* For performance reasons, the A/B testing component requires you to
|
||||
* setup a cache (APC or Memcached) and use the MongoDB database. The
|
||||
* amount of data in the MongoDB should not be that big for most of
|
||||
* the websites and as such it is fine if you are using the 32bit
|
||||
* version of MongoDB.
|
||||
*
|
||||
* For the moment the storage is not abstracted to use another database.
|
||||
*
|
||||
* All the configuration variables for the component start with
|
||||
* `pluf_ab_`. You need to add 'Pluf_AB' to your list of middleware.
|
||||
*
|
||||
*/
|
||||
class Pluf_AB
|
||||
{
|
||||
/**
|
||||
* MongoDB database handler.
|
||||
*/
|
||||
public static $db = null;
|
||||
|
||||
/**
|
||||
* Returns an alternative for a given test.
|
||||
*
|
||||
* The middleware is already storing the uid of the user and makes
|
||||
* it available as $request->pabuid.
|
||||
*
|
||||
* @param $test string Unique name of the test
|
||||
* @param $request Pluf_HTTP_Request
|
||||
* @param $alts array Alternatives to pick from (array(true,false))
|
||||
* @param $weights array Weights for the alternatives (null)
|
||||
* @param $desc string Optional description of the test ('')
|
||||
* @return mixed One value from $alts
|
||||
*/
|
||||
public static function test($test, &$request, $alts=array(true,false),
|
||||
$weights=null, $desc='')
|
||||
{
|
||||
if (Pluf::f('pluf_ab_allow_force', false) and
|
||||
isset($request->GET[$test])) {
|
||||
return $alts[$request->GET[$test]];
|
||||
}
|
||||
$db = self::getDb();
|
||||
// Get or set test
|
||||
$dtest = $db->tests->findOne(array('_id' => $test),
|
||||
array('_id', 'active', 'winner'));
|
||||
if ($dtest == null) {
|
||||
$dtest = array('_id' => $test,
|
||||
'creation_dtime' => gmdate('Y-m-d H:i:s',
|
||||
$request->time),
|
||||
'desc' => $desc,
|
||||
'alts' => $alts,
|
||||
'exp' => 0,
|
||||
'conv' => 0,
|
||||
'active' => true);
|
||||
for ($i=0;$i<count($alts);$i++) {
|
||||
$dtest['expalt_'.$i] = 0;
|
||||
$dtest['convalt_'.$i] = 0;
|
||||
}
|
||||
$db->tests->update(array('_id'=>$test), $dtest,
|
||||
array('upsert' => true));
|
||||
} elseif (!$dtest['active']) {
|
||||
// If test closed with given alternative, returns alternative
|
||||
return (isset($dtest['winner'])) ? $alts[$dtest['winner']] : $alts[0];
|
||||
}
|
||||
if (!isset($request->pabuid)) {
|
||||
$request->pabuid = self::getUid($request);
|
||||
}
|
||||
if ($request->pabuid == 'bot') {
|
||||
return $alts[0];
|
||||
}
|
||||
// If $request->pabuid in test, returns corresponding alternative
|
||||
$intest = $db->intest->findOne(array('_id' => $test.'##'.$request->pabuid),
|
||||
array('_id', 'alt'));
|
||||
if ($intest) {
|
||||
return $alts[$intest['alt']];
|
||||
}
|
||||
// Else find alternative, store and return it
|
||||
if ($weights == null) {
|
||||
$weights = array_fill(0, count($alts), 1.0/count($alts));
|
||||
}
|
||||
$alt = self::weightedRand($weights);
|
||||
$intest = array('_id' => $test.'##'.$request->pabuid,
|
||||
'test' => $test,
|
||||
'pabuid' => $request->pabuid,
|
||||
'first_dtime' => gmdate('Y-m-d H:i:s',
|
||||
$request->time),
|
||||
'alt' => $alt);
|
||||
$db->intest->update(array('_id' => $test.'##'.$request->pabuid),
|
||||
$intest, array('upsert' => true));
|
||||
// Update the counts of the test
|
||||
$db->tests->update(array('_id' => $test),
|
||||
array('$inc' => array('exp' => 1,
|
||||
'expalt_'.$alt => 1)));
|
||||
return $alts[$alt];
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a test as converted.
|
||||
*
|
||||
* A user which was not exposed to the test or a bot is not marked
|
||||
* as converted as it is not significant.
|
||||
*
|
||||
* @param $test string Test
|
||||
* @param $request Pluf_HTTP_Request
|
||||
*/
|
||||
public static function convert($test, $request)
|
||||
{
|
||||
if (!isset($request->pabuid) or $request->pabuid == 'bot') {
|
||||
return;
|
||||
}
|
||||
$db = self::getDb();
|
||||
$id = $test.'##'.$request->pabuid;
|
||||
$intest = $db->intest->findOne(array('_id' => $id),
|
||||
array('_id', 'alt'));
|
||||
if (!$intest) {
|
||||
// Not tested
|
||||
return;
|
||||
}
|
||||
$conv = $db->convert->findOne(array('_id' => $id));
|
||||
if ($conv) {
|
||||
// Already converted
|
||||
return;
|
||||
}
|
||||
$dtest = $db->tests->findOne(array('_id' => $test));
|
||||
if (!$dtest or !$dtest['active']) {
|
||||
return;
|
||||
}
|
||||
$conv = array(
|
||||
'_id' => $id,
|
||||
'test' => $test,
|
||||
);
|
||||
$db->convert->update(array('_id' => $id), $conv,
|
||||
array('upsert' => true));
|
||||
// increment the test counters
|
||||
$db->tests->update(array('_id' => $test),
|
||||
array('$inc' => array('conv' => 1,
|
||||
'convalt_'.$intest['alt'] => 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a property set for the user.
|
||||
*
|
||||
* This allows you to segment your users with these properties.
|
||||
*
|
||||
* @param $request Pluf_HTTP_Request
|
||||
* @param $props array Properties
|
||||
*/
|
||||
public static function register(&$request, $props)
|
||||
{
|
||||
$pabuid = (isset($request->pabuid)) ?
|
||||
$request->pabuid :
|
||||
self::getUid($request);
|
||||
if ($pabuid == 'bot') {
|
||||
return;
|
||||
}
|
||||
$request->pabuid = $pabuid;
|
||||
$request->pabprops = array_merge($request->pabprops, $props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Track a funnel.
|
||||
*
|
||||
* The array of properties can be used to track different A/B
|
||||
* testing cases.
|
||||
*
|
||||
* The list of properties must be the same at all the steps of the
|
||||
* funnel, you cannot pass array('gender' => 'M') at step 1 and
|
||||
* array('age' => 32) at step 2. You need to pass both of them at
|
||||
* all steps.
|
||||
*
|
||||
* @param $funnel string Name of the funnel
|
||||
* @param $step int Step in the funnel, from 1 to n
|
||||
* @param $stepname string Readable name for the step
|
||||
* @param $request Pluf_HTTP_Request Request object
|
||||
* @param $props array Array of properties associated with the funnel (array())
|
||||
*/
|
||||
public static function trackFunnel($funnel, $step, $stepname, $request, $props=array())
|
||||
{
|
||||
$pabuid = (isset($request->pabuid)) ?
|
||||
$request->pabuid :
|
||||
self::getUid($request);
|
||||
if ($pabuid == 'bot') {
|
||||
return;
|
||||
}
|
||||
$request->pabuid = $pabuid;
|
||||
$cache = Pluf_Cache::factory();
|
||||
$key = 'pluf_ab_funnel_'.crc32($funnel.'#'.$step.'#'.$pabuid);
|
||||
if ($cache->get($key, false)) {
|
||||
return; // The key is valid 60s not to track 2 steps within 60s
|
||||
}
|
||||
$cache->set($key, '1', 60);
|
||||
$what = array(
|
||||
'f' => $funnel,
|
||||
's' => $step,
|
||||
'sn' => $stepname,
|
||||
't' => (int) gmdate('Ymd', $request->time),
|
||||
'u' => $pabuid,
|
||||
'p' => array_merge($request->pabprops, $props),
|
||||
);
|
||||
$db = self::getDb();
|
||||
$db->funnellogs->insert($what);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the response of a view.
|
||||
*
|
||||
* If the request has no cookie and the request has a pabuid, set
|
||||
* the cookie in the response.
|
||||
*
|
||||
* @param Pluf_HTTP_Request The request
|
||||
* @param Pluf_HTTP_Response The response
|
||||
* @return Pluf_HTTP_Response The response
|
||||
*/
|
||||
function process_response($request, $response)
|
||||
{
|
||||
if (!isset($request->COOKIE['pabuid']) and isset($request->pabuid)
|
||||
and $request->pabuid != 'bot') {
|
||||
$response->cookies['pabuid'] = $request->pabuid;
|
||||
}
|
||||
if (isset($request->pabprops) and count($request->pabprops)
|
||||
and $request->pabuid != 'bot') {
|
||||
$response->cookies['pabprops'] = Pluf_Sign::dumps($request->pabprops, null, true);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the request.
|
||||
*
|
||||
* If the request has the A/B test cookie, set $request->pabuid.
|
||||
*
|
||||
* @param Pluf_HTTP_Request The request
|
||||
* @return bool False
|
||||
*/
|
||||
function process_request($request)
|
||||
{
|
||||
if (isset($request->COOKIE['pabuid']) and
|
||||
self::check_uid($request->COOKIE['pabuid'])) {
|
||||
$request->pabuid = $request->COOKIE['pabuid'];
|
||||
}
|
||||
$request->pabprops = array();
|
||||
if (isset($request->COOKIE['pabprops'])) {
|
||||
try {
|
||||
$request->pabprops = Pluf_Sign::loads($request->COOKIE['pabprops']);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a MongoDB database handle.
|
||||
*
|
||||
* It opens only one connection per request and tries to keep a
|
||||
* persistent connection between the requests.
|
||||
*
|
||||
* The configuration keys used are:
|
||||
*
|
||||
* `pluf_ab_mongo_server`: 'mongodb://localhost:27017'
|
||||
* `pluf_ab_mongo_options`: array('connect' => true,
|
||||
* 'persist' => 'pluf_ab_mongo')
|
||||
* `pluf_ab_mongo_db`: 'pluf_ab'
|
||||
*
|
||||
* If you have a default installation of MongoDB, it should work
|
||||
* out of the box.
|
||||
*
|
||||
*/
|
||||
public static function getDb()
|
||||
{
|
||||
if (self::$db !== null) {
|
||||
return self::$db;
|
||||
}
|
||||
$server = Pluf::f('pluf_ab_mongo_server', 'mongodb://localhost:27017');
|
||||
$options = Pluf::f('pluf_ab_mongo_options',
|
||||
array('connect' => true, 'persist' => 'pluf_ab_mongo'));
|
||||
$conn = new Mongo($server, $options);
|
||||
self::$db = $conn->selectDB(Pluf::f('pluf_ab_mongo_db', 'pluf_ab'));
|
||||
return self::$db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the uid of a given request.
|
||||
*
|
||||
* @param $request Pluf_HTTP_Request
|
||||
*/
|
||||
public static function getUid($request)
|
||||
{
|
||||
if (isset($request->COOKIE['pabuid']) and
|
||||
self::check_uid($request->COOKIE['pabuid'])) {
|
||||
return $request->COOKIE['pabuid'];
|
||||
}
|
||||
if (!isset($request->SERVER['HTTP_USER_AGENT']) or
|
||||
self::isBot($request->SERVER['HTTP_USER_AGENT'])) {
|
||||
return 'bot';
|
||||
}
|
||||
// Here we need to make an uid, first check if a user with
|
||||
// same ip/agent exists and was last seen within the last 1h.
|
||||
// We get that from MemcacheDB
|
||||
$cache = Pluf_Cache::factory();
|
||||
$key = 'pluf_ab_'.crc32($request->remote_addr.'#'.$request->SERVER['HTTP_USER_AGENT']);
|
||||
if ($uid=$cache->get($key, null)) {
|
||||
$cache->set($key, $uid, 3600);
|
||||
return $uid;
|
||||
}
|
||||
$uid = self::make_uid($request);
|
||||
$cache->set($key, $uid, 3600);
|
||||
return $uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given user agent is a bot.
|
||||
*
|
||||
* @param $user_agent string User agent string
|
||||
* @return bool True if the user agent is a bot
|
||||
*/
|
||||
public static function isBot($user_agent)
|
||||
{
|
||||
static $bots = array('robot', 'checker', 'crawl', 'discovery',
|
||||
'hunter', 'scanner', 'spider', 'sucker', 'larbin',
|
||||
'slurp', 'libwww', 'lwp', 'yandex', 'netcraft',
|
||||
'wget', 'twiceler');
|
||||
static $pbots = array('/bot[\s_+:,\.\;\/\\\-]/i',
|
||||
'/[\s_+:,\.\;\/\\\-]bot/i');
|
||||
foreach ($bots as $r) {
|
||||
if (false !== stristr($user_agent, $r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
foreach ($pbots as $p) {
|
||||
if (preg_match($p, $user_agent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (false === strpos($user_agent, '(')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random weighted alternative.
|
||||
*
|
||||
* Given a series of weighted alternative in the format:
|
||||
*
|
||||
* <pre>
|
||||
* array('alt1' => 0.2,
|
||||
* 'alt2' => 0.3,
|
||||
* 'alt3' => 0.5);
|
||||
* </pre>
|
||||
*
|
||||
* Returns the key of the selected alternative. In the following
|
||||
* example, the alternative 3 (alt3) has a 50% chance to be
|
||||
* selected, if the selected the results would be 'alt3'.
|
||||
|
||||
* @link: http://20bits.com/downloads/w_rand.phps
|
||||
*
|
||||
* @param $weights array Weighted alternatives
|
||||
* @return mixed Key of the selected $weights array
|
||||
*/
|
||||
public static function weightedRand($weights)
|
||||
{
|
||||
$r = mt_rand(1,10000);
|
||||
$offset = 0;
|
||||
foreach ($weights as $k => $w) {
|
||||
$offset += $w*10000;
|
||||
if ($r <= $offset) {
|
||||
return $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a request, make a corresponding A/B test UID.
|
||||
*
|
||||
* The UID is based on the time, the remote address, a random
|
||||
* component and is hashed to ensure the integrity and avoid the
|
||||
* need of a database hit when controlled.
|
||||
*
|
||||
* @param $request Pluf_HTTP_Request
|
||||
* @return string UID
|
||||
*/
|
||||
public static function make_uid($request)
|
||||
{
|
||||
$base = sprintf('%08X%08X%08X', $request->time,
|
||||
sprintf('%u', crc32($request->remote_addr)),
|
||||
rand());
|
||||
return sprintf('%s%08X', $base, sprintf('%u', crc32($base.md5(Pluf::f('secret_key')))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the uid in the cookie.
|
||||
*
|
||||
* @see self::make_uid
|
||||
*
|
||||
* @param $uid string The UID
|
||||
* @return bool True if the UID is valid
|
||||
*/
|
||||
public static function check_uid($uid)
|
||||
{
|
||||
if (strlen($uid) != 32) {
|
||||
return false;
|
||||
}
|
||||
$check = sprintf('%08X', sprintf('%u', crc32(substr($uid, 0, 24).md5(Pluf::f('secret_key')))));
|
||||
return ($check == substr($uid, -8));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
*
|
||||
* Statistics Functions
|
||||
*
|
||||
* Note: I am not a statistician, use at your own risk!
|
||||
*
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* Given a conversion rate calculate the recommended sample sizes.
|
||||
*
|
||||
* The sample sizes is calculated to be significant at 95% in the
|
||||
* case of a variation of conversion with respect to the other
|
||||
* alternative of 25%, 15% and 5%.
|
||||
*
|
||||
* @param $conv Conversion rate ]0.0;1.0]
|
||||
* @return array The 3 sample sizes for 25%, 15% and 5%
|
||||
*/
|
||||
public static function ssize($conv)
|
||||
{
|
||||
$a = 3.84145882689; // $a = pow(inverse_ncdf(1-(1-0.95)/2),2)
|
||||
$res = array();
|
||||
$bs = array(0.0625, 0.0225, 0.0025);
|
||||
foreach ($bs as $b) {
|
||||
$res[] = (int) ((1-$conv)*$a/($b*$conv));
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a test, returns the corresponding stats.
|
||||
*
|
||||
* @param $test array Test definition and results
|
||||
* @return array Statistics for the test
|
||||
*/
|
||||
public static function getTestStats($test)
|
||||
{
|
||||
$stats = array(); // Will store the stats
|
||||
$n = count($test['alts']);
|
||||
$aconvr = array(); // All the conversion rates to sort the alternatives
|
||||
for ($i=0;$i<$n;$i++) {
|
||||
$conv = (isset($test['convalt_'.$i])) ? $test['convalt_'.$i] : 0;
|
||||
$exp = (isset($test['expalt_'.$i])) ? $test['expalt_'.$i] : 0;
|
||||
$convr = self::cr(array($exp, $conv));
|
||||
$nconvr = ($convr !== null) ?
|
||||
sprintf('%01.2f%%', $convr*100.0) : 'N/A';
|
||||
$ssize = ($convr !== null and $convr > 0) ?
|
||||
self::ssize($convr) : array();
|
||||
$stats[] = array('alt' => $i,
|
||||
'convr' => $convr,
|
||||
'conv' => $conv,
|
||||
'exp' => $exp,
|
||||
'nconvr' => $nconvr,
|
||||
'ssize' => $ssize);
|
||||
$aconvr[] = ($convr === null) ? 0 : $convr;
|
||||
}
|
||||
array_multisort($aconvr, SORT_DESC, $stats);
|
||||
// We want the best to be significantly better than the second best.
|
||||
for ($i=0;$i<$n;$i++) {
|
||||
$convr = $stats[$i]['convr'];
|
||||
$exp = $stats[$i]['exp'];
|
||||
$conv = $stats[$i]['conv'];
|
||||
$comp = false;
|
||||
$zscore = false;
|
||||
$conf = false;
|
||||
$better = false;
|
||||
if ($i != 1 and $stats[1]['convr'] > 0) {
|
||||
// Compare with base case and get confidence/Z-score
|
||||
$comp = 100.0 * (float) ($convr - $stats[1]['convr'])/ (float) ($stats[1]['convr']);
|
||||
if ($comp > 0) $better = true;
|
||||
$comp = sprintf('%01.2f%%', $comp);
|
||||
$zscore = self::zscore(array($stats[1]['exp'], $stats[1]['conv']),
|
||||
array($exp, $conv));
|
||||
$conf = sprintf('%01.2f%%', self::cumnormdist($zscore)*100.0);
|
||||
$zscore = sprintf('%01.2f', $zscore);
|
||||
}
|
||||
$stats[$i]['comp'] = $comp;
|
||||
$stats[$i]['zscore'] = $zscore;
|
||||
$stats[$i]['conf'] = $conf;
|
||||
$stats[$i]['better'] = $better;
|
||||
}
|
||||
return $stats;
|
||||
}
|
||||
|
||||
public static function cr($t)
|
||||
{
|
||||
if ($t[1] < 0) return null;
|
||||
if ($t[0] <= 0) return null;
|
||||
return $t[1]/$t[0];
|
||||
}
|
||||
|
||||
public static function zscore($c, $t)
|
||||
{
|
||||
$z = self::cr($t)-self::cr($c);
|
||||
$s = (self::cr($t)*(1-self::cr($t)))/$t[0]
|
||||
+ (self::cr($c)*(1-self::cr($c)))/$c[0];
|
||||
return $z/sqrt($s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximation of the cumulative normal distribution.
|
||||
*/
|
||||
public static function cumnormdist($x)
|
||||
{
|
||||
$b1 = 0.319381530;
|
||||
$b2 = -0.356563782;
|
||||
$b3 = 1.781477937;
|
||||
$b4 = -1.821255978;
|
||||
$b5 = 1.330274429;
|
||||
$p = 0.2316419;
|
||||
$c = 0.39894228;
|
||||
|
||||
if($x >= 0.0) {
|
||||
$t = 1.0 / ( 1.0 + $p * $x );
|
||||
return (1.0 - $c * exp( -$x * $x / 2.0 ) * $t *
|
||||
( $t *( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ));
|
||||
} else {
|
||||
$t = 1.0 / ( 1.0 - $p * $x );
|
||||
return ( $c * exp( -$x * $x / 2.0 ) * $t *
|
||||
( $t *( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ));
|
||||
}
|
||||
}
|
||||
}
|
86
pluf/src/Pluf/AB/Form/MarkWinner.php
Normal file
86
pluf/src/Pluf/AB/Form/MarkWinner.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Mark the winner of a test.
|
||||
*
|
||||
* This form is not used to display the form, only to validate and
|
||||
* process it.
|
||||
*
|
||||
*/
|
||||
class Pluf_AB_Form_MarkWinner extends Pluf_Form
|
||||
{
|
||||
protected $test = null; /**< Store the test retrieved during validation. */
|
||||
|
||||
public function initFields($extra=array())
|
||||
{
|
||||
$this->fields['test'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => true)
|
||||
);
|
||||
$this->fields['alt'] = new Pluf_Form_Field_Integer(
|
||||
array('required' => true,
|
||||
'min' => 0,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the test exists, is active and the corresponding
|
||||
* alternative exists too.
|
||||
*
|
||||
* The validation is at the global level to prevent the need of a
|
||||
* form per test and simplify the dashboard design.
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
$db = Pluf_AB::getDb();
|
||||
$test = $db->tests->findOne(array('_id' => $this->cleaned_data['test']));
|
||||
if ($test == null) {
|
||||
throw new Pluf_Form_Invalid(__('The test has not been found.'));
|
||||
}
|
||||
if (!$test['active']) {
|
||||
throw new Pluf_Form_Invalid(__('The test is already inactive.'));
|
||||
}
|
||||
if (!isset($test['alts'][$this->cleaned_data['alt']])) {
|
||||
throw new Pluf_Form_Invalid(__('This alternative is not available.'));
|
||||
}
|
||||
// Good we have the test and the right alternative
|
||||
$this->test = $test;
|
||||
return $this->cleaned_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the test.
|
||||
*
|
||||
* @return array Test.
|
||||
*/
|
||||
function save($commit=true)
|
||||
{
|
||||
$this->test['winner'] = $this->cleaned_data['alt'];
|
||||
$this->test['active'] = false;
|
||||
$this->test['stop_dtime'] = gmdate('Y-m-d H:i:s');
|
||||
$db = Pluf_AB::getDb();
|
||||
$db->tests->update(array('_id'=> $this->cleaned_data['test']),
|
||||
$this->test);
|
||||
return $this->test;
|
||||
}
|
||||
}
|
219
pluf/src/Pluf/AB/Funnel.php
Normal file
219
pluf/src/Pluf/AB/Funnel.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Funnel statistics.
|
||||
*
|
||||
* Funnels are easy to track but not that easy to generate statistics
|
||||
* out of them.
|
||||
*
|
||||
* Stats are compiled "by GMT day", so you can track your funnel per
|
||||
* day, week or more. Stats are put in cache in the "funnels" collection.
|
||||
*
|
||||
*/
|
||||
class Pluf_AB_Funnel
|
||||
{
|
||||
/**
|
||||
* Returns the list of funnels.
|
||||
*
|
||||
* @return array Funnels
|
||||
*/
|
||||
public static function getFunnels()
|
||||
{
|
||||
$db = Pluf_AB::getDb();
|
||||
foreach (array('f', 't') as $k) {
|
||||
// Once created, it will return immediately in the future
|
||||
// calls so the overhead is negligeable.
|
||||
$db->funnellogs->ensureIndex(array($k => 1),
|
||||
array('background' => true));
|
||||
}
|
||||
$nf = $db->command(array('distinct' => 'funnellogs', 'key' => 'f'));
|
||||
if ((int) $nf['ok'] == 1) {
|
||||
sort($nf['values']);
|
||||
return $nf['values'];
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the properties for a given period.
|
||||
*/
|
||||
public static function getFunnelProps($funnel, $period='today')
|
||||
{
|
||||
$db = Pluf_AB::getDb();
|
||||
switch ($period) {
|
||||
case 'yesterday':
|
||||
$q = array('t' => (int) gmdate('Ymd', time()-86400));
|
||||
break;
|
||||
case 'today':
|
||||
$q = array('t' => (int) gmdate('Ymd'));
|
||||
break;
|
||||
case '7days':
|
||||
$q = array('t' => array('$gte' => (int) gmdate('Ymd', time()-604800)));
|
||||
break;
|
||||
case 'all':
|
||||
default:
|
||||
$q = array();
|
||||
break;
|
||||
}
|
||||
$q['f'] = $funnel;
|
||||
$props = array();
|
||||
foreach ($db->funnellogs->find($q) as $log) {
|
||||
foreach ($log['p'] as $prop => $v) {
|
||||
if (isset($props[$prop]) and !in_array($v, $props[$prop])) {
|
||||
$props[$prop][] = $v;
|
||||
} else {
|
||||
$props[$prop] = array($v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stats for a given funnel.
|
||||
*
|
||||
* @param $funnel string Funnel
|
||||
* @param $period string Time period 'yesterday', ('today'), '7days', 'all'
|
||||
* @param $prop string Property to filter (null)
|
||||
*/
|
||||
public static function getStats($funnel, $period='today', $prop=null)
|
||||
{
|
||||
$db = Pluf_AB::getDb();
|
||||
$steps = array();
|
||||
for ($i=1;$i<=20;$i++) {
|
||||
$steps[$i] = array();
|
||||
}
|
||||
switch ($period) {
|
||||
case 'yesterday':
|
||||
$q = array('t' => (int) gmdate('Ymd', time()-86400));
|
||||
break;
|
||||
case 'today':
|
||||
$q = array('t' => (int) gmdate('Ymd'));
|
||||
break;
|
||||
case '7days':
|
||||
$q = array('t' => array('$gte' => (int) gmdate('Ymd', time()-604800)));
|
||||
break;
|
||||
case 'all':
|
||||
default:
|
||||
$q = array();
|
||||
break;
|
||||
}
|
||||
$q['f'] = $funnel;
|
||||
if ($prop) {
|
||||
$q['p.'.$prop] = array('$exists' => true);
|
||||
}
|
||||
$uids = array();
|
||||
// With very big logs, we will need to find by schunks, this
|
||||
// will be very easy to adapt.
|
||||
foreach ($db->funnellogs->find($q) as $log) {
|
||||
if (!isset($uids[$log['u'].'##'.$log['s']])) {
|
||||
if ($prop and !isset($log['p'][$prop])) {
|
||||
continue;
|
||||
}
|
||||
$uids[$log['u'].'##'.$log['s']] = true;
|
||||
$step = $log['s'];
|
||||
$steps[$step]['name'] = $log['sn'];
|
||||
$steps[$step]['id'] = $log['s'];
|
||||
if ($prop and !isset($steps[$step]['props'])) {
|
||||
$steps[$step]['props'] = array();
|
||||
}
|
||||
$steps[$step]['total'] = (isset($steps[$step]['total'])) ?
|
||||
$steps[$step]['total'] + 1 : 1;
|
||||
if ($prop) {
|
||||
$steps[$step]['props'][$log['p'][$prop]] = (isset($steps[$step]['props'][$log['p'][$prop]])) ?
|
||||
$steps[$step]['props'][$log['p'][$prop]] + 1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now, compile the stats for steps 2 to n
|
||||
// First, we find the "max" for the reference number of
|
||||
// visitors along this funnel. This is $t1 and $tprops[prop]
|
||||
$t1 = 0;
|
||||
foreach ($steps as $step) {
|
||||
if (isset($step['total']) and $step['total'] > $t1) {
|
||||
$t1 = $step['total'];
|
||||
}
|
||||
if ($prop and isset($step['props'])) {
|
||||
foreach ($step['props'] as $v => $t) {
|
||||
if (!isset($tprops[$v])) {
|
||||
$tprops[$v] = $t;
|
||||
continue;
|
||||
}
|
||||
if ($tprops[$v] < $t) {
|
||||
$tprops[$v] = $t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($t1 == 0) {
|
||||
return array();
|
||||
}
|
||||
$prev_step = null;
|
||||
for ($i=1;$i<=20;$i++) {
|
||||
if ($prev_step == null) {
|
||||
|
||||
}
|
||||
if ($steps[$i]) {
|
||||
$tp = $prev_step['total'];
|
||||
$tn = $steps[$i]['total'];
|
||||
if ($tp) {
|
||||
$steps[$i]['conv'] = sprintf('%01.2f%%', 100.0 - (float)($tp-$tn)/$tp*100.0);
|
||||
} else {
|
||||
$steps[$i]['conv'] = 'N/A';
|
||||
}
|
||||
if ($t1) {
|
||||
$steps[$i]['conv1'] = sprintf('%01.2f%%', 100.0 - (float)($t1-$tn)/$t1*100.0);
|
||||
} else {
|
||||
$steps[$i]['conv1'] = 'N/A';
|
||||
}
|
||||
if ($prop) {
|
||||
$steps[$i]['sprops'] = array();
|
||||
$steps[$i]['sprops1'] = array();
|
||||
foreach ($steps[$i]['props'] as $v => $t) {
|
||||
if (!isset($tprops[$v])) {
|
||||
$tprops[$v] = $t;
|
||||
}
|
||||
$pv = isset($prev_step['props'][$v]) ? $prev_step['props'][$v] : 0;
|
||||
$steps[$i]['sprops'][$v] = array($t, $pv);
|
||||
$steps[$i]['sprops1'][$v] = array($t, $tprops[$v]);
|
||||
if ($pv) {
|
||||
$steps[$i]['sprops'][$v][] = round(100*(float)$t/(float)$pv,2).'%';
|
||||
} else {
|
||||
$steps[$i]['sprops'][$v][] = 0;
|
||||
}
|
||||
$steps[$i]['sprops1'][$v][] = round(100*(float)$t/(float)$tprops[$v],2).'%';
|
||||
}
|
||||
}
|
||||
$steps[$i]['bigtotal'] = $t1;
|
||||
$prev_step = $steps[$i];
|
||||
}
|
||||
}
|
||||
for ($i=20;$i>=1;$i--) {
|
||||
if (!$steps[$i]) {
|
||||
unset($steps[$i]); // We remove the inexisting steps
|
||||
}
|
||||
}
|
||||
return $steps;
|
||||
}
|
||||
}
|
176
pluf/src/Pluf/AB/Views.php
Normal file
176
pluf/src/Pluf/AB/Views.php
Normal file
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
|
||||
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
|
||||
|
||||
/**
|
||||
* Manage and visualize the tests.
|
||||
*
|
||||
* It is possible to mark a test as inactive by picking a
|
||||
* winner.
|
||||
*
|
||||
* Check the urls.php file for the URL definition to integrate the
|
||||
* dashboard in your application/project.
|
||||
*
|
||||
* The permission used are:
|
||||
*
|
||||
* Pluf_AB.view-dashboard: The user can view the dasboard.
|
||||
* Pluf_AB.edit-test: The user can edit a test.
|
||||
*
|
||||
*/
|
||||
class Pluf_AB_Views
|
||||
{
|
||||
/**
|
||||
* Display the currently running tests.
|
||||
*
|
||||
* The name of the view in the urls must be 'pluf_ab_dashboard'.
|
||||
*/
|
||||
public $dasboard_precond = array(array('Pluf_Precondition::hasPerm',
|
||||
'Pluf_AB.view-dashboard'));
|
||||
public function dashboard($request, $match)
|
||||
{
|
||||
$url = Pluf_HTTP_URL_urlForView('pluf_ab_dashboard');
|
||||
$can_edit = $request->user->hasPerm('Pluf_AB.edit-test');
|
||||
if ($can_edit && $request->method == 'POST') {
|
||||
// We mark the winner.
|
||||
$form = new Pluf_AB_Form_MarkWinner($request->POST);
|
||||
if ($form->isValid()) {
|
||||
$form->save();
|
||||
$request->user->setMessage(__('The test has been updated.'));
|
||||
return new Pluf_HTTP_Response_Redirect($url);
|
||||
}
|
||||
} else {
|
||||
// To have it available for the control of the errors in
|
||||
// the template.
|
||||
$form = new Pluf_AB_Form_MarkWinner();
|
||||
}
|
||||
// Get the list of tests
|
||||
$db = Pluf_AB::getDb();
|
||||
$active = array();
|
||||
$stopped = array();
|
||||
foreach ($db->tests->find() as $test) {
|
||||
$test['stats'] = Pluf_AB::getTestStats($test);
|
||||
if ($test['active']) {
|
||||
$active[] = $test;
|
||||
} else {
|
||||
$stopped[] = $test;
|
||||
}
|
||||
}
|
||||
return Pluf_Shortcuts_RenderToResponse('pluf/ab/dashboard.html',
|
||||
array('active' => $active,
|
||||
'stopped' => $stopped,
|
||||
'form' => $form,
|
||||
'can_edit' => $can_edit,
|
||||
),
|
||||
$request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the list of funnels.
|
||||
*
|
||||
*/
|
||||
public $funnels_precond = array(array('Pluf_Precondition::hasPerm',
|
||||
'Pluf_AB.view-funnels'));
|
||||
public function funnels($request, $match)
|
||||
{
|
||||
$url = Pluf_HTTP_URL_urlForView('pluf_ab_funnels');
|
||||
$funnels = Pluf_AB_Funnel::getFunnels();
|
||||
return Pluf_Shortcuts_RenderToResponse('pluf/ab/funnels.html',
|
||||
array('funnels' => $funnels,
|
||||
),
|
||||
$request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a given funnel stats.
|
||||
*
|
||||
*/
|
||||
public $funnel_precond = array(array('Pluf_Precondition::hasPerm',
|
||||
'Pluf_AB.view-funnels'));
|
||||
public function funnel($request, $match)
|
||||
{
|
||||
$periods = array('yesterday' => __('Yesterday'),
|
||||
'today' => __('Today'),
|
||||
'7days' => __('Last 7 days'),
|
||||
'all' => __('All time'));
|
||||
$period = 'today';
|
||||
$nperiod = $periods[$period];
|
||||
if (isset($request->REQUEST['p'])
|
||||
and isset($periods[$request->REQUEST['p']])) {
|
||||
$period = $request->REQUEST['p'];
|
||||
$nperiod = $periods[$request->REQUEST['p']];
|
||||
}
|
||||
$props = Pluf_AB_Funnel::getFunnelProps($match[1], $period);
|
||||
$prop = null;
|
||||
if (isset($request->REQUEST['prop']) and
|
||||
in_array($request->REQUEST['prop'], array_keys($props))) {
|
||||
$prop = $request->REQUEST['prop'];
|
||||
}
|
||||
$stats = Pluf_AB_Funnel::getStats($match[1], $period, $prop);
|
||||
return Pluf_Shortcuts_RenderToResponse('pluf/ab/funnel.html',
|
||||
array('stats' => $stats,
|
||||
'funnel' => $match[1],
|
||||
'nperiod' => $nperiod,
|
||||
'period' => $period,
|
||||
'props' => $props,
|
||||
'prop' => $prop,
|
||||
),
|
||||
$request);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple view to redirect a user and convert it.
|
||||
*
|
||||
* To convert the user for the test 'my_test' and redirect it to
|
||||
* the URL 'http://www.example.com' add the following view in your
|
||||
* urls.php:
|
||||
*
|
||||
* <pre>
|
||||
* array('regex' => '#^/goto/example/$#',
|
||||
* 'base' => $base,
|
||||
* 'model' => 'Pluf_AB_Views',
|
||||
* 'method' => 'convRedirect',
|
||||
* 'name' => 'go_to_example',
|
||||
* 'params' => array('url' => 'http://www.example.com',
|
||||
* 'test' => 'my_test')
|
||||
* );
|
||||
* </pre>
|
||||
*
|
||||
* Try to put a url which reflects the final url after redirection
|
||||
* to minimize the confusion for the user. In this example, in
|
||||
* your code or template you use the named url 'go_to_example'.
|
||||
*
|
||||
*/
|
||||
public function convRedirect($request, $match, $p)
|
||||
{
|
||||
Pluf_AB::convert($p['test'], $request);
|
||||
return new Pluf_HTTP_Response_Redirect($p['url']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
139
pluf/src/Pluf/Auth/LdapBackend.php
Normal file
139
pluf/src/Pluf/Auth/LdapBackend.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Backend to authenticate against a LDAP server.
|
||||
*
|
||||
* Configuration is done with the 'auth_ldap_*' keys.
|
||||
*/
|
||||
class Pluf_Auth_LdapBackend
|
||||
{
|
||||
/**
|
||||
* Given a user id, retrieve it.
|
||||
*
|
||||
* Here we get the against the model database.
|
||||
*/
|
||||
public static function getUser($user_id)
|
||||
{
|
||||
$user_model = Pluf::f('pluf_custom_user','Pluf_User');
|
||||
$sql = new Pluf_SQL('login=%s', array($user_id));
|
||||
return Pluf::factory($user_model)->getOne($sql->gen());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array with the authentication data, auth the user and return it.
|
||||
*/
|
||||
public static function authenticate($auth_data)
|
||||
{
|
||||
$password = $auth_data['password'];
|
||||
$login = $auth_data['login'];
|
||||
|
||||
// Small security check against the login
|
||||
if (preg_match('/[^A-Za-z0-9\-\_]/', $login)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We check the user against the LDAP server, if it works we
|
||||
// are happy, if not return false.
|
||||
|
||||
|
||||
$ldap_dn = Pluf::f('auth_ldap_dn', 'ou=users,dc=example,dc=com');
|
||||
$ldap_user = Pluf::f('auth_ldap_user', null);
|
||||
$ldap_password = Pluf::f('auth_ldap_password', null);
|
||||
$ldap_version = Pluf::f('auth_ldap_version', 3);
|
||||
$ldap_user_key = Pluf::f('auth_ldap_user_key', 'uid');
|
||||
// If auth_ldap_password_key, it will use crypt hash control
|
||||
// to test the login password, else it will bind.
|
||||
$ldap_password_key = Pluf::f('auth_ldap_password_key', null);
|
||||
$ldap_surname_key = Pluf::f('auth_ldap_surname_key', 'sn');
|
||||
$ldap_givenname_key = Pluf::f('auth_ldap_givenname_key', 'cn');
|
||||
$ldap_email_key = Pluf::f('auth_ldap_email_key', 'mail');
|
||||
|
||||
|
||||
$ldap = ldap_connect(Pluf::f('auth_ldap_host', 'localhost'));
|
||||
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION,
|
||||
Pluf::f('auth_ldap_version', 3));
|
||||
if (!ldap_bind($ldap, $ldap_user, $ldap_password)) {
|
||||
Pluf_Log::warn(sprintf('Cannot bind to the ldap server, user:%s, password:***', $ldap_user));
|
||||
ldap_close($ldap);
|
||||
return false;
|
||||
}
|
||||
// Go for a search
|
||||
$search = ldap_search($ldap, $ldap_dn,
|
||||
'('.$ldap_user_key.'='.$login.')',
|
||||
array($ldap_user_key, $ldap_surname_key,
|
||||
$ldap_givenname_key, $ldap_email_key));
|
||||
$n = ldap_get_entries($ldap, $search);
|
||||
if ($n['count'] != 1) {
|
||||
ldap_close($ldap);
|
||||
return false;
|
||||
}
|
||||
$entry = ldap_first_entry($ldap, $search);
|
||||
// We get all the data first, the bind or hash control is done
|
||||
// later. If we control with bind now, we need to search again
|
||||
// to have an $entry resource to get the values.
|
||||
list($family_name,) = @ldap_get_values($ldap, $entry, $ldap_surname_key);
|
||||
list($first_name,) = @ldap_get_values($ldap, $entry, $ldap_givenname_key);
|
||||
list($email,) = @ldap_get_values($ldap, $entry, $ldap_email_key);
|
||||
$user_dn = ldap_get_dn($ldap, $entry);
|
||||
|
||||
|
||||
if ($ldap_password_key) {
|
||||
// Password authentication.
|
||||
list($ldap_hash,) = ldap_get_values($ldap, $entry, $ldap_password_key);
|
||||
$ldap_hash = substr($ldap_hash, 7);
|
||||
$salt = substr($ldap_hash, 0, 12);
|
||||
$hash = crypt($password, $salt);
|
||||
if ($ldap_hash != $hash) {
|
||||
ldap_close($ldap);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Bind authentication
|
||||
if (!@ldap_bind($ldap, $user_dn, $password)) {
|
||||
ldap_close($ldap);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// We get the user values as the
|
||||
// Now we get the user and we create it if not available
|
||||
$user = self::getUser($login);
|
||||
if ($user) {
|
||||
ldap_close($ldap);
|
||||
return $user;
|
||||
}
|
||||
// Need to create it
|
||||
ldap_close($ldap);
|
||||
$user_model = Pluf::f('pluf_custom_user','Pluf_User');
|
||||
$user = new $user_model();
|
||||
$user->active = true;
|
||||
$user->login = $login;
|
||||
$user->password = $password;
|
||||
$user->last_name = $family_name;
|
||||
$user->first_name = $first_name;
|
||||
$user->email = $email;
|
||||
$user->create();
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
58
pluf/src/Pluf/Auth/ModelBackend.php
Normal file
58
pluf/src/Pluf/Auth/ModelBackend.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Backend to authenticate against the Pluf_User model.
|
||||
*/
|
||||
class Pluf_Auth_ModelBackend
|
||||
{
|
||||
/**
|
||||
* Given a user id, retrieve it.
|
||||
*
|
||||
* In the case of the Pluf_User backend, the $user_id is the login.
|
||||
*/
|
||||
public static function getUser($user_id)
|
||||
{
|
||||
$user_model = Pluf::f('pluf_custom_user','Pluf_User');
|
||||
$sql = new Pluf_SQL('login=%s', array($user_id));
|
||||
return Pluf::factory($user_model)->getOne($sql->gen());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array with the authentication data, auth the user and return it.
|
||||
*/
|
||||
public static function authenticate($auth_data)
|
||||
{
|
||||
$password = $auth_data['password'];
|
||||
$login = $auth_data['login'];
|
||||
$user = self::getUser($login);
|
||||
if (!$user) {
|
||||
return false;
|
||||
}
|
||||
if (!$user->active) {
|
||||
return false;
|
||||
}
|
||||
return ($user->checkPassword($password)) ? $user : false;
|
||||
}
|
||||
}
|
||||
|
90
pluf/src/Pluf/Cache.php
Normal file
90
pluf/src/Pluf/Cache.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Cache class.
|
||||
*
|
||||
* You should not use this class directly, but one of the subclasses
|
||||
* implementing a given engine. This is done automatically when using
|
||||
* the factory. It will use the engine defined by the 'cache_engine'
|
||||
* configuration variable.
|
||||
*
|
||||
* Default timeout in seconds is defined by the 'cache_timeout'
|
||||
* configuration variable.
|
||||
*
|
||||
* <pre>
|
||||
* $cache = new Pluf_Cache::factory();
|
||||
* if (null === ($foo=$cache->get('my-key'))) {
|
||||
* $foo = run_complex_operation();
|
||||
* $cache->set('my-key', $foo);
|
||||
* }
|
||||
* return $foo;
|
||||
* </pre>
|
||||
*
|
||||
* The value to be stored in the cache must be serializable.
|
||||
*
|
||||
* @see http://www.php.net/serialize
|
||||
*/
|
||||
class Pluf_Cache
|
||||
{
|
||||
/**
|
||||
* Factory.
|
||||
*
|
||||
* @return Pluf_Cache_* Cache object
|
||||
*/
|
||||
public static function factory()
|
||||
{
|
||||
if (false === ($engine=Pluf::f('cache_engine', false))) {
|
||||
throw new Pluf_Exception_SettingError('"cache_engine" setting not defined.');
|
||||
}
|
||||
if (!isset($GLOBALS['_PX_Pluf_Cache-'.$engine])) {
|
||||
$GLOBALS['_PX_Pluf_Cache-'.$engine] = new $engine();
|
||||
}
|
||||
return $GLOBALS['_PX_Pluf_Cache-'.$engine];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the cache.
|
||||
*
|
||||
* @param string Key to store the information
|
||||
* @param mixed Value to store
|
||||
* @param int Timeout in seconds (null)
|
||||
* @return bool Success
|
||||
*/
|
||||
public function set($key, $value, $timeout=null)
|
||||
{
|
||||
throw new Pluf_Exception_NotImplemented();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value from the cache.
|
||||
*
|
||||
* @param string Key to get the information
|
||||
* @param mixed Default value to return if cache miss (null)
|
||||
* @param mixed Stored value or default
|
||||
*/
|
||||
public function get($key, $default=null)
|
||||
{
|
||||
throw new Pluf_Exception_NotImplemented();
|
||||
}
|
||||
}
|
102
pluf/src/Pluf/Cache/Apc.php
Normal file
102
pluf/src/Pluf/Cache/Apc.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* APC based cache.
|
||||
*
|
||||
* You need APC installed on your server for this cache system to
|
||||
* work. You can install APC with <code>$ sudo pecl install apc</code>
|
||||
* on most systems.
|
||||
*
|
||||
* A special 'cache_apc_keyprefix' can be set to use APC for different
|
||||
* applications and avoid conflict. Compression is performed at the
|
||||
* PHP level using the gz(in|de)flate functions.
|
||||
*
|
||||
* Example of configuration:
|
||||
*
|
||||
* <pre>
|
||||
* $cfg['cache_engine'] = 'Pluf_Cache_Apc';
|
||||
* $cfg['cache_timeout'] = 300;
|
||||
* $cfg['cache_apc_keyprefix'] = 'uniqueforapp';
|
||||
* $cfg['cache_apc_compress'] = true;
|
||||
* </pre>
|
||||
*
|
||||
* @see Pluf_Cache
|
||||
* @see http://www.php.net/gzdeflate
|
||||
* @see http://www.php.net/gzinflate
|
||||
*/
|
||||
class Pluf_Cache_Apc extends Pluf_Cache
|
||||
{
|
||||
/**
|
||||
* Prefix added to all the keys.
|
||||
*/
|
||||
private $keyprefix = '';
|
||||
|
||||
/**
|
||||
* Auto compress the data to save memory against a small
|
||||
* performance loss.
|
||||
*/
|
||||
private $compress = false;
|
||||
|
||||
/**
|
||||
* Create the cache object and initialize it from the
|
||||
* configuration.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->keyprefix = Pluf::f('cache_apc_keyprefix', '');
|
||||
$this->compress = Pluf::f('cache_apc_compress', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the cache.
|
||||
*
|
||||
* @param string Key to store the information
|
||||
* @param mixed Value to store
|
||||
* @param int Timeout in seconds (null)
|
||||
* @return bool Success
|
||||
*/
|
||||
public function set($key, $value, $timeout=null)
|
||||
{
|
||||
if ($timeout == null) $timeout = Pluf::f('cache_timeout', 300);
|
||||
$value = serialize($value);
|
||||
if ($this->compress) $value = gzdeflate($value, 9);
|
||||
return apc_store($this->keyprefix.$key, $value, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value from the cache.
|
||||
*
|
||||
* @param string Key to get the information
|
||||
* @param mixed Default value to return if cache miss (null)
|
||||
* @return mixed Stored value or default
|
||||
*/
|
||||
public function get($key, $default=null)
|
||||
{
|
||||
$success = false;
|
||||
$value = apc_fetch($this->keyprefix.$key, &$success);
|
||||
if (!$success) return $default;
|
||||
if ($this->compress) $value = gzinflate($value);
|
||||
return unserialize($value);
|
||||
}
|
||||
}
|
132
pluf/src/Pluf/Cache/File.php
Normal file
132
pluf/src/Pluf/Cache/File.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* File based cache.
|
||||
*
|
||||
* Info are stored in the 'cache_file_folder' folder. In the folder, 2
|
||||
* subdirectories are created based on the md5 of the key.
|
||||
*/
|
||||
class Pluf_Cache_File extends Pluf_Cache
|
||||
{
|
||||
/**
|
||||
* Is debug mode?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $_debug;
|
||||
|
||||
/**
|
||||
* Mapping key => md5.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_keymap = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (!Pluf::f('cache_file_folder', false)) {
|
||||
throw new Pluf_Exception_SettingError('"cache_file_folder" setting not defined.');
|
||||
}
|
||||
|
||||
$this->_debug = Pluf::f('debug', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the cache.
|
||||
*
|
||||
* @param string Key to store the information
|
||||
* @param mixed Value to store
|
||||
* @param int Timeout in seconds (null)
|
||||
* @return bool Success
|
||||
*/
|
||||
public function set($key, $value, $timeout=null)
|
||||
{
|
||||
$fname = $this->_keyToFile($key);
|
||||
$dir = dirname($fname);
|
||||
if (null === $timeout) {
|
||||
$timeout = Pluf::f('cache_timeout', 300);
|
||||
}
|
||||
if (!file_exists($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
$expire = $_SERVER['REQUEST_TIME'] + $timeout;
|
||||
$success = file_put_contents($fname, $expire."\n".serialize($value), LOCK_EX);
|
||||
chmod($fname, 0777);
|
||||
|
||||
return (false === $success) ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value from the cache.
|
||||
*
|
||||
* @param string Key to get the information
|
||||
* @param mixed Default value to return if cache miss (null)
|
||||
* @param mixed Stored value or default
|
||||
*/
|
||||
public function get($key, $default=null)
|
||||
{
|
||||
$fname = $this->_keyToFile($key);
|
||||
if (!file_exists($fname)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($this->_debug) {
|
||||
ob_start();
|
||||
include $fname;
|
||||
$data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
} else {
|
||||
$data = file_get_contents($fname);
|
||||
}
|
||||
list($timeout, $content) = explode("\n", $data, 2);
|
||||
|
||||
if ($timeout < $_SERVER['REQUEST_TIME']) {
|
||||
@unlink($fname);
|
||||
return $default;
|
||||
}
|
||||
|
||||
return unserialize($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a key into a path to a file.
|
||||
*
|
||||
* @param string Key
|
||||
* @return string Path to file
|
||||
*/
|
||||
public function _keyToFile($key)
|
||||
{
|
||||
if (isset($this->_keymap[$key])) {
|
||||
$md5 = $this->_keymap[$key];
|
||||
} else {
|
||||
$md5 = md5($key);
|
||||
$this->_keymap[$key] = $md5;
|
||||
}
|
||||
|
||||
return Pluf::f('cache_file_folder') . '/' .
|
||||
substr($md5, 0, 2) . '/' .
|
||||
substr($md5, 2, 2) . '/' .
|
||||
substr($md5, 4);
|
||||
}
|
||||
}
|
94
pluf/src/Pluf/Cache/Memcached.php
Normal file
94
pluf/src/Pluf/Cache/Memcached.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Memcached based cache.
|
||||
*
|
||||
* A special 'cache_memcached_keyprefix' can be set to use one
|
||||
* memcached for different applications and avoid conflict.
|
||||
*
|
||||
* Example of configuration:
|
||||
*
|
||||
* <pre>
|
||||
* $cfg['cache_engine'] = 'Pluf_Cache_Memcached';
|
||||
* $cfg['cache_timeout'] = 300;
|
||||
* $cfg['cache_memcached_keyprefix'] = 'uniqueforapp';
|
||||
* $cfg['cache_memcached_server'] = 'localhost';
|
||||
* $cfg['cache_memcached_port'] = 11211;
|
||||
* $cfg['cache_memcached_compress'] = 0; (or MEMCACHE_COMPRESSED)
|
||||
* </pre>
|
||||
*/
|
||||
class Pluf_Cache_Memcached extends Pluf_Cache
|
||||
{
|
||||
private $memcache = null;
|
||||
private $keyprefix = '';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->memcache = memcache_connect(Pluf::f('cache_memcached_server', 'localhost'),
|
||||
Pluf::f('cache_memcached_port', 11211));
|
||||
if (false === $this->memcache) {
|
||||
$this->memcache = null;
|
||||
}
|
||||
$this->keyprefix = Pluf::f('cache_memcached_keyprefix', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the cache.
|
||||
*
|
||||
* @param string Key to store the information
|
||||
* @param mixed Value to store
|
||||
* @param int Timeout in seconds (null)
|
||||
* @return bool Success
|
||||
*/
|
||||
public function set($key, $value, $timeout=null)
|
||||
{
|
||||
if ($this->memcache) {
|
||||
if ($timeout == null) $timeout = Pluf::f('cache_timeout', 300);
|
||||
$this->memcache->set($this->keyprefix.$key, serialize($value),
|
||||
Pluf::f('cache_memcached_compress', 0),
|
||||
$timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value from the cache.
|
||||
*
|
||||
* @param string Key to get the information
|
||||
* @param mixed Default value to return if cache miss (null)
|
||||
* @param mixed Stored value or default
|
||||
*/
|
||||
public function get($key, $default=null)
|
||||
{
|
||||
if ($this->memcache) {
|
||||
$val = $this->memcache->get($this->keyprefix.$key);
|
||||
if (false === $val) {
|
||||
return $default;
|
||||
} else {
|
||||
return unserialize($val);
|
||||
}
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
}
|
485
pluf/src/Pluf/Calendar.php
Normal file
485
pluf/src/Pluf/Calendar.php
Normal file
@@ -0,0 +1,485 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Calendar to display a list of events in a calendar table.
|
||||
*
|
||||
* The calendar is independent of other elements of Pluf, you can use
|
||||
* it standalone if you want.
|
||||
*
|
||||
* The principle is that you set options and feed the calendar with a
|
||||
* list of events. Based on the options, the render() method will
|
||||
* produce different views of the calendar.
|
||||
*/
|
||||
class Pluf_Calendar
|
||||
{
|
||||
/**
|
||||
* The list of events to display.
|
||||
*/
|
||||
var $events = array();
|
||||
var $summary = '';
|
||||
|
||||
/**
|
||||
* The display options of the calendar.
|
||||
*/
|
||||
var $opts = array();
|
||||
|
||||
// When updating an interval, if a col span more rows and columns,
|
||||
// store the info for the next rows to compensate as needed.
|
||||
var $bspans = array();
|
||||
|
||||
/**
|
||||
* List of events without the events not between the start/end
|
||||
* days.
|
||||
*/
|
||||
var $_events = array();
|
||||
|
||||
/**
|
||||
* List of time intervals in the $_events list.
|
||||
*/
|
||||
var $_time_intervals = array();
|
||||
|
||||
/**
|
||||
* Simultaneous events at a given time slot, for a given group.
|
||||
*
|
||||
* array('2007-03-25' =>
|
||||
* array(array('time' => '10:15',
|
||||
* 'start' => 4 ,
|
||||
* 'continued' => 5),
|
||||
* array('time' => '11:30',
|
||||
* 'start' => 3 ,
|
||||
* 'continued' => 0),
|
||||
* )
|
||||
* '2007-03-24' =>
|
||||
* array(array('time' => '11:30',
|
||||
* 'start' => 2 ,
|
||||
* 'continued' => 3),
|
||||
* )
|
||||
* )
|
||||
*
|
||||
*/
|
||||
var $_simultaneous = array();
|
||||
var $_max_simultaneous = array();
|
||||
var $_groups = array();
|
||||
|
||||
/**
|
||||
* Render the calendar based on the options.
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if (count($this->events) == 0) {
|
||||
return '';
|
||||
}
|
||||
$this->cleanEventList();
|
||||
$this->getTimeIntervals();
|
||||
$this->getSimultaneous();
|
||||
$this->getMaxSimultaneous();
|
||||
$s = '';
|
||||
if ($this->summary) {
|
||||
$s = 'summary="'.htmlspecialchars($this->summary).'" ';
|
||||
}
|
||||
$out = '<table '.$s.'cellspacing="0" class="px-calendar">'."\n";
|
||||
$out .= $this->getHead();
|
||||
$out .= $this->getBody();
|
||||
$out .= '</table>'."\n";
|
||||
return Pluf_Template_SafeString::markSafe($out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event are grouped by day per default, you can group as you
|
||||
* want, just subclass this method. Groups are used to make
|
||||
* columns in the table with the headings.
|
||||
*/
|
||||
function getEventGroup($event)
|
||||
{
|
||||
return substr($event['start'], 0, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the available groups.
|
||||
*/
|
||||
function getGroups()
|
||||
{
|
||||
if (count($this->_groups)) {
|
||||
return $this->_groups;
|
||||
}
|
||||
foreach ($this->_events as $event) {
|
||||
$group = $this->getEventGroup($event);
|
||||
if (!in_array($group, $this->_groups)) {
|
||||
$this->_groups[] = $group;
|
||||
}
|
||||
}
|
||||
return $this->_groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of a group to print in the headers.
|
||||
*/
|
||||
function getGroupName($group)
|
||||
{
|
||||
$dw = $this->daysOfWeek();
|
||||
$days = date('w', strtotime($group));
|
||||
return htmlspecialchars($dw[$days%7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the body of the calendar.
|
||||
*/
|
||||
function getBody()
|
||||
{
|
||||
$out = '<tbody>'."\n";
|
||||
$inters = $this->getTimeIntervals();
|
||||
$groups = $this->getGroups();
|
||||
for ($i=0;$i<(count($inters)-1);$i++) {
|
||||
$out .= '<tr>'."\n";
|
||||
$out .= ' <th scope="row">'.$inters[$i].' - '.$inters[$i+1].'</th>'."\n";
|
||||
foreach ($groups as $group) {
|
||||
$out .= $this->getEventCell($group, $inters[$i]);
|
||||
}
|
||||
$out .= '</tr>'."\n";
|
||||
}
|
||||
$out .= '</tbody>'."\n";
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value to print for the given cell
|
||||
*
|
||||
* @param string Current group
|
||||
* @param string Current interval
|
||||
* @return string Table cells
|
||||
*/
|
||||
function getEventCell($group, $inter)
|
||||
{
|
||||
$out = '';
|
||||
$max = $this->getMaxSimultaneous();
|
||||
$fullspanevent = false;
|
||||
foreach ($this->_events as $event) {
|
||||
// Get the start time of the event
|
||||
$e_start = substr($event['start'], 11, 5);
|
||||
if ($e_start != $inter) {
|
||||
// If the event does not start at the current time,
|
||||
// skip it
|
||||
continue;
|
||||
}
|
||||
if ($group != $this->getEventGroup($event)) {
|
||||
// Check if full span even at this time interval
|
||||
if (!empty($event['fullspan'])) {
|
||||
$fullspanevent = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Find how many rows the event will span
|
||||
$extra = '';
|
||||
$content = '';
|
||||
if (!isset($event['content'])) $event['content'] = '';
|
||||
$row_span = $this->getEventRowSpanning($event, $this->_time_intervals);
|
||||
if ($row_span > 1) {
|
||||
$extra .= ' rowspan="'.$row_span.'"';
|
||||
}
|
||||
if (!empty($event['fullspan'])) {
|
||||
$colspan = 0;
|
||||
foreach ($max as $_s) {
|
||||
$colspan += $_s;
|
||||
}
|
||||
$extra .= ' colspan="'.$colspan.'"';
|
||||
$fullspanevent = true;
|
||||
}
|
||||
if (strlen($event['color']) > 0) {
|
||||
$extra .= ' style="background-color: '.$event['color'].';"';
|
||||
}
|
||||
if (strlen($event['content']) > 0) {
|
||||
$content .= $event['content'];
|
||||
}
|
||||
if (strlen($event['url']) > 0) {
|
||||
$content .= '<a href="'.$event['url'].'">'.htmlspecialchars($event['title']).'</a>';
|
||||
}
|
||||
if (strlen($event['content']) == 0 and strlen($event['url']) == 0) {
|
||||
$content .= htmlspecialchars($event['title']);
|
||||
}
|
||||
$out .= ' <td'.$extra.'>'.$content.'</td>'."\n";
|
||||
}
|
||||
if (!$fullspanevent) {
|
||||
$sim = null;
|
||||
foreach ($this->_simultaneous[$group] as $_sim) {
|
||||
if ($_sim['time'] == $inter) {
|
||||
$sim = $_sim;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$diff = $max[$group] - ($sim['start'] + $sim['continued']);
|
||||
for ($k=0; $k<$diff; $k++) {
|
||||
$out .= ' <td class="empty"> </td>'."\n";
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event spanning over the rows.
|
||||
*
|
||||
* @param array Event
|
||||
* @param array Intervals
|
||||
* @return int Spanning
|
||||
*/
|
||||
function getEventRowSpanning($event, $inters)
|
||||
{
|
||||
$start = substr($event['start'], 11, 5);
|
||||
$end = substr($event['end'], 11, 5);
|
||||
$span = 1;
|
||||
foreach ($inters as $inter) {
|
||||
if ($inter < $end and $inter > $start) {
|
||||
$span++;
|
||||
}
|
||||
}
|
||||
return $span;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the head of the calendar.
|
||||
*/
|
||||
function getHead()
|
||||
{
|
||||
$out = '<thead>'."\n".'<tr>'."\n".' <th> </th>'."\n";
|
||||
// Print the groups.
|
||||
$groups = $this->getGroups();
|
||||
$max = $this->getMaxSimultaneous();
|
||||
foreach ($groups as $group) {
|
||||
if ($max[$group] > 1) {
|
||||
$span = ' colspan="'.$max[$group].'"';
|
||||
} else {
|
||||
$span = '';
|
||||
}
|
||||
$out .= ' <th scope="col"'.$span.'>'.$this->getGroupName($group).'</th>'."\n";
|
||||
}
|
||||
$out .= '</tr>'."\n".'</thead>'."\n";
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rowspan for each day.
|
||||
*/
|
||||
function getDaySpanning()
|
||||
{
|
||||
list($start, $end) = $this->getStartEndDays();
|
||||
$inters = $this->getTimeIntervals($start, $end);
|
||||
$n = $this->getDayNumber($start, $end);
|
||||
$inter_n = array_fill(0, count($inters), 0);
|
||||
$day_span = array_fill(0, $n+1, $inter_n);
|
||||
foreach ($this->events as $event) {
|
||||
// The event must be between $start and $end
|
||||
$e_dstart = substr($event['start'], 0, 10);
|
||||
$e_dend = substr($event['end'], 0, 10);
|
||||
if ($e_dend < $start or $e_dstart > $end) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$day = $this->getDayNumber($start, substr($event['end'], 0, 10));
|
||||
$e_start = substr($event['start'], 11, 5);
|
||||
$e_end = substr($event['end'], 11, 5);
|
||||
$i = 0;
|
||||
foreach ($inters as $inter) {
|
||||
if ($inter < $e_end and $inter >= $e_start) {
|
||||
$day_span[$day][$i]++;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $day_span;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array with the days of the week.
|
||||
*/
|
||||
function daysOfWeek()
|
||||
{
|
||||
return array(
|
||||
__('Sunday'),
|
||||
__('Monday'),
|
||||
__('Tuesday'),
|
||||
__('Wednesday'),
|
||||
__('Thursday'),
|
||||
__('Friday'),
|
||||
__('Saturday'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of days to list.
|
||||
*
|
||||
* @param string Start date
|
||||
* @param string End date
|
||||
* @return int Number of days
|
||||
*/
|
||||
function getDayNumber($start, $end)
|
||||
{
|
||||
Pluf::loadFunction('Pluf_Date_Compare');
|
||||
$diff = Pluf_Date_Compare($start.' 00:00:00', $end.' 00:00:00');
|
||||
return (int) $diff/86400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start and end dates based on the event list.
|
||||
*
|
||||
* @return array (start day, end day)
|
||||
*/
|
||||
function getStartEndDays()
|
||||
{
|
||||
$start = '9999-12-31';
|
||||
$end = '0000-01-01';
|
||||
if (!isset($this->opts['start-day'])
|
||||
or !isset($this->opts['end-day'])) {
|
||||
foreach ($this->events as $event) {
|
||||
$t_start = substr($event['start'], 0, 10);
|
||||
$t_end = substr($event['end'], 0, 10);
|
||||
if ($t_start < $start) {
|
||||
$start = $t_start;
|
||||
}
|
||||
if ($t_end > $end) {
|
||||
$end = $t_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($this->opts['start-day'])) {
|
||||
$start = $this->opts['start-day'];
|
||||
} else {
|
||||
$this->opts['start-day'] = $start;
|
||||
}
|
||||
if (isset($this->opts['end-day'])) {
|
||||
$end = $this->opts['end-day'];
|
||||
} else {
|
||||
$this->opts['end-day'] = $end;
|
||||
}
|
||||
return array($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean event list.
|
||||
*/
|
||||
function cleanEventList()
|
||||
{
|
||||
list($start, $end) = $this->getStartEndDays();
|
||||
$this->_events = array();
|
||||
foreach ($this->events as $event) {
|
||||
$e_dstart = substr($event['start'], 0, 10);
|
||||
$e_dend = substr($event['end'], 0, 10);
|
||||
if ($e_dend < $start or $e_dstart > $end) {
|
||||
continue;
|
||||
}
|
||||
$this->_events[] = $event;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time intervals. They span all the groups.
|
||||
*/
|
||||
function getTimeIntervals($start='', $end='')
|
||||
{
|
||||
if (count($this->_time_intervals)) {
|
||||
return $this->_time_intervals;
|
||||
}
|
||||
$intervals = array();
|
||||
foreach ($this->_events as $event) {
|
||||
$t = substr($event['start'], 11, 5);
|
||||
if (!in_array($t, $intervals)) {
|
||||
$intervals[] = $t;
|
||||
}
|
||||
$t = substr($event['end'], 11, 5);
|
||||
if (!in_array($t, $intervals)) {
|
||||
$intervals[] = $t;
|
||||
}
|
||||
}
|
||||
sort($intervals);
|
||||
$this->_time_intervals = $intervals;
|
||||
return $intervals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get simultaneous events at the same time slot and same group.
|
||||
*/
|
||||
function getSimultaneous()
|
||||
{
|
||||
foreach ($this->getGroups() as $group) {
|
||||
$this->_simultaneous[$group] = array();
|
||||
foreach ($this->_time_intervals as $inter) {
|
||||
$this->_simultaneous[$group][] = array('time' => $inter,
|
||||
'start' => 0,
|
||||
'continued' => 0);
|
||||
}
|
||||
}
|
||||
foreach ($this->_events as $event) {
|
||||
$group = $this->getEventGroup($event);
|
||||
$e_tstart = substr($event['start'], 11, 5);
|
||||
$e_tend = substr($event['end'], 11, 5);
|
||||
foreach ($this->_simultaneous[$group] as $index=>$inter) {
|
||||
if ($e_tstart == $inter['time']) {
|
||||
$inter['start'] += 1;
|
||||
$this->_simultaneous[$group][$index] = $inter;
|
||||
continue;
|
||||
}
|
||||
if ($e_tstart < $inter['time'] and $e_tend > $inter['time']) {
|
||||
$inter['continued'] += 1;
|
||||
$this->_simultaneous[$group][$index] = $inter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->_simultaneous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum simultaneous events
|
||||
*/
|
||||
function getMaxSimultaneous()
|
||||
{
|
||||
if (count($this->_max_simultaneous) > 0) {
|
||||
return $this->_max_simultaneous;
|
||||
}
|
||||
foreach ($this->getGroups() as $group) {
|
||||
$this->_max_simultaneous[$group] = 0;
|
||||
}
|
||||
foreach ($this->_simultaneous as $group=>$choices) {
|
||||
foreach ($choices as $count) {
|
||||
if ($this->_max_simultaneous[$group] < $count['start'] + $count['continued']) {
|
||||
$this->_max_simultaneous[$group] = $count['start'] + $count['continued'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->_max_simultaneous;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overloading of the get method.
|
||||
*
|
||||
* @param string Property to get
|
||||
*/
|
||||
function __get($prop)
|
||||
{
|
||||
if ($prop == 'render') return $this->render();
|
||||
return $this->$prop;
|
||||
}
|
||||
|
||||
}
|
111
pluf/src/Pluf/Crypt.php
Normal file
111
pluf/src/Pluf/Crypt.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple encryption class.
|
||||
*
|
||||
* Very simple encryption class to perform simple encryption. It can
|
||||
* be used for example when you request a valid email address to
|
||||
* register. The validation link can contain the encrypted email.
|
||||
*
|
||||
* DO NOT EVER USE IT FOR REALLY IMPORTANT DATA!!!
|
||||
*
|
||||
* Credit Anonymous on http://www.php.net/mcrypt
|
||||
*/
|
||||
class Pluf_Crypt
|
||||
{
|
||||
public $key = '';
|
||||
|
||||
/**
|
||||
* Construct the encryption object.
|
||||
*
|
||||
* @param string The encryption key ('')
|
||||
*/
|
||||
function __construct($key='')
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a string with a key.
|
||||
*
|
||||
* If the key is not given, $this->key is used. If $this->key is
|
||||
* empty an exception is raised.
|
||||
*
|
||||
* @param string String to encode
|
||||
* @param string Encryption key ('')
|
||||
* @return string Encoded string
|
||||
*/
|
||||
function encrypt($string, $key='')
|
||||
{
|
||||
if ($key == '') {
|
||||
$key = $this->key;
|
||||
}
|
||||
if ($key == '') {
|
||||
throw new Exception('No encryption key provided.');
|
||||
}
|
||||
$result = '';
|
||||
$strlen = strlen($string);
|
||||
$keylen = strlen($key);
|
||||
for($i=0; $i<$strlen; $i++) {
|
||||
$char = substr($string, $i, 1);
|
||||
$keychar = substr($key, ($i % $keylen)-1, 1);
|
||||
$char = chr(ord($char)+ord($keychar));
|
||||
$result.=$char;
|
||||
}
|
||||
$result = base64_encode($result);
|
||||
return str_replace(array('+','/','='), array('-','_','~'), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a string with a key.
|
||||
*
|
||||
* If the key is not given, $this->key is used. If $this->key is
|
||||
* empty an exception is raised.
|
||||
*
|
||||
* @param string String to decode
|
||||
* @param string Encryption key ('')
|
||||
* @return string Decoded string
|
||||
*/
|
||||
function decrypt($string, $key='')
|
||||
{
|
||||
if ($key == '') {
|
||||
$key = $this->key;
|
||||
}
|
||||
if ($key == '') {
|
||||
throw new Exception('No encryption key provided.');
|
||||
}
|
||||
$result = '';
|
||||
$string = str_replace(array('-','_','~'), array('+','/','='), $string);
|
||||
$string = base64_decode($string);
|
||||
$strlen = strlen($string);
|
||||
$keylen = strlen($key);
|
||||
for($i=0; $i<$strlen; $i++) {
|
||||
$char = substr($string, $i, 1);
|
||||
$keychar = substr($key, ($i % $keylen)-1, 1);
|
||||
$char = chr(ord($char)-ord($keychar));
|
||||
$result.=$char;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
225
pluf/src/Pluf/DB.php
Normal file
225
pluf/src/Pluf/DB.php
Normal file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Database class.
|
||||
*
|
||||
* Depending of the parameters, the database object will connect to a MySQL
|
||||
* or SQLite database.
|
||||
*/
|
||||
class Pluf_DB
|
||||
{
|
||||
|
||||
/**
|
||||
* Get a database connection.
|
||||
*/
|
||||
static function get($engine, $server, $database, $login, $password,
|
||||
$prefix, $debug=false, $version='')
|
||||
{
|
||||
$engine = 'Pluf_DB_'.$engine;
|
||||
$con = new $engine($login, $password, $server, $database,
|
||||
$prefix, $debug, $version);
|
||||
return $con;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default DB connection.
|
||||
*
|
||||
* The default database connection is defined in the configuration file
|
||||
* through the following configuration variables:
|
||||
* - db_login : Login to connect to the database
|
||||
* - db_password : Password to the database
|
||||
* - db_server : Name of the server
|
||||
* - db_database : Name of the database
|
||||
* - db_table_prefix : Prefix for the table names
|
||||
* - db_version : Version of the database engine
|
||||
* - db_engine : Engine for exampe 'MySQL', 'SQLite'
|
||||
*
|
||||
* Once the first connection is created the following calls to Pluf::db()
|
||||
* are getting the same connection.
|
||||
*
|
||||
*/
|
||||
function Pluf_DB_getConnection($extra=null)
|
||||
{
|
||||
if (isset($GLOBALS['_PX_db']) &&
|
||||
(is_resource($GLOBALS['_PX_db']->con_id) or is_object($GLOBALS['_PX_db']->con_id))) {
|
||||
return $GLOBALS['_PX_db'];
|
||||
}
|
||||
$GLOBALS['_PX_db'] = Pluf_DB::get(Pluf::f('db_engine'),
|
||||
Pluf::f('db_server'),
|
||||
Pluf::f('db_database'),
|
||||
Pluf::f('db_login'),
|
||||
Pluf::f('db_password'),
|
||||
Pluf::f('db_table_prefix'),
|
||||
Pluf::f('db_debug'),
|
||||
Pluf::f('db_version'));
|
||||
return $GLOBALS['_PX_db'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of default typecast and quoting for the database ORM.
|
||||
*
|
||||
* Foreach field type you need to provide an array with 2 functions,
|
||||
* the from_db, the to_db.
|
||||
*
|
||||
* $value = from_db($value);
|
||||
* $escaped_value = to_db($value, $dbobject);
|
||||
*
|
||||
* $escaped_value is ready to be put in the SQL, that is if this is a
|
||||
* string, the value is quoted and escaped for example with SQLite:
|
||||
* 'my string'' is escaped' or with MySQL 'my string\' is escaped' the
|
||||
* starting ' and ending ' are included!
|
||||
*
|
||||
* @return array Default typecast.
|
||||
*/
|
||||
function Pluf_DB_defaultTypecast()
|
||||
{
|
||||
return array(
|
||||
'Pluf_DB_Field_Boolean' =>
|
||||
array('Pluf_DB_BooleanFromDb', 'Pluf_DB_BooleanToDb'),
|
||||
'Pluf_DB_Field_Date' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_Datetime' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_Email' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_File' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_Float' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_Foreignkey' =>
|
||||
array('Pluf_DB_IntegerFromDb', 'Pluf_DB_IntegerToDb'),
|
||||
'Pluf_DB_Field_Integer' =>
|
||||
array('Pluf_DB_IntegerFromDb', 'Pluf_DB_IntegerToDb'),
|
||||
'Pluf_DB_Field_Password' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_PasswordToDb'),
|
||||
'Pluf_DB_Field_Sequence' =>
|
||||
array('Pluf_DB_IntegerFromDb', 'Pluf_DB_IntegerToDb'),
|
||||
'Pluf_DB_Field_Slug' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_SlugToDb'),
|
||||
'Pluf_DB_Field_Text' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_Varchar' =>
|
||||
array('Pluf_DB_IdentityFromDb', 'Pluf_DB_IdentityToDb'),
|
||||
'Pluf_DB_Field_Serialized' =>
|
||||
array('Pluf_DB_SerializedFromDb', 'Pluf_DB_SerializedToDb'),
|
||||
'Pluf_DB_Field_Compressed' =>
|
||||
array('Pluf_DB_CompressedFromDb', 'Pluf_DB_CompressedToDb'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identity function.
|
||||
*
|
||||
* @param mixed Value
|
||||
* @return mixed Value
|
||||
*/
|
||||
function Pluf_DB_IdentityFromDb($val)
|
||||
{
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identity function.
|
||||
*
|
||||
* @param mixed Value.
|
||||
* @param object Database handler.
|
||||
* @return string Ready to use for SQL.
|
||||
*/
|
||||
function Pluf_DB_IdentityToDb($val, $db)
|
||||
{
|
||||
if (null === $val) {
|
||||
return 'NULL';
|
||||
}
|
||||
return $db->esc($val);
|
||||
}
|
||||
|
||||
function Pluf_DB_SerializedFromDb($val)
|
||||
{
|
||||
if ($val) {
|
||||
return unserialize($val);
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
function Pluf_DB_SerializedToDb($val, $db)
|
||||
{
|
||||
if (null === $val) {
|
||||
return 'NULL';
|
||||
}
|
||||
return $db->esc(serialize($val));
|
||||
}
|
||||
|
||||
function Pluf_DB_CompressedFromDb($val)
|
||||
{
|
||||
return ($val) ? gzinflate($val) : $val;
|
||||
}
|
||||
|
||||
function Pluf_DB_CompressedToDb($val, $db)
|
||||
{
|
||||
return (null === $val) ? 'NULL' : $db->esc(gzdeflate($val, 9));
|
||||
}
|
||||
|
||||
function Pluf_DB_BooleanFromDb($val) {
|
||||
if ($val) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Pluf_DB_BooleanToDb($val, $db) {
|
||||
if (null === $val) {
|
||||
return 'NULL';
|
||||
}
|
||||
if ($val) {
|
||||
return $db->esc('1');
|
||||
}
|
||||
return $db->esc('0');
|
||||
}
|
||||
|
||||
function Pluf_DB_IntegerFromDb($val) {
|
||||
return (null === $val) ? null : (int) $val;
|
||||
}
|
||||
|
||||
function Pluf_DB_IntegerToDb($val, $db) {
|
||||
return (null === $val) ? 'NULL' : (string)(int)$val;
|
||||
}
|
||||
|
||||
function Pluf_DB_PasswordToDb($val, $db) {
|
||||
//$exp = explode(':', $val);
|
||||
//if (in_array($exp[0], array('sha1', 'md5', 'crc32'))) {
|
||||
// return $db->esc($val);
|
||||
//}
|
||||
// We need to hash the value.
|
||||
//$salt = Pluf_Utils::getRandomString(5);
|
||||
//return $db->esc('sha1:'.$salt.':'.sha1($salt.$val));
|
||||
if (base64_encode(base64_decode($val)) == $val)
|
||||
return $db->esc($val);
|
||||
else
|
||||
return $db->esc(base64_encode(sha1($val, TRUE)));
|
||||
}
|
||||
|
||||
function Pluf_DB_SlugToDB($val, $db) {
|
||||
return $db->esc(Pluf_DB_Field_Slug::slugify($val));
|
||||
}
|
112
pluf/src/Pluf/DB/Field.php
Normal file
112
pluf/src/Pluf/DB/Field.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Default database field.
|
||||
*/
|
||||
class Pluf_DB_Field
|
||||
{
|
||||
/**
|
||||
* The types are defined in the $mappings member variable of the
|
||||
* schema class of your database engine, for example
|
||||
* Pluf_DB_Schema_MySQL.
|
||||
*/
|
||||
public $type = '';
|
||||
|
||||
/**
|
||||
* The column name of the field.
|
||||
*/
|
||||
public $column = '';
|
||||
|
||||
/**
|
||||
* Current value of the field.
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* All the extra parameters of the field.
|
||||
*/
|
||||
public $extra = array();
|
||||
|
||||
/**
|
||||
* The extra methods added to the model by the field.
|
||||
*/
|
||||
public $methods = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed Value ('')
|
||||
* @param string Column name ('')
|
||||
*/
|
||||
function __construct($value='', $column='', $extra=array())
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->column = $column;
|
||||
if ($extra) {
|
||||
$this->extra = array_merge($this->extra, $extra);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form field for this field.
|
||||
*
|
||||
* We put this method at the field level as it allows us to easily
|
||||
* create a new DB field and a new Form field and use them without
|
||||
* the need to modify another place where the mapping would be
|
||||
* performed.
|
||||
*
|
||||
* @param array Definition of the field.
|
||||
* @param string Form field class.
|
||||
*/
|
||||
function formField($def, $form_field='Pluf_Form_Field_Varchar')
|
||||
{
|
||||
Pluf::loadClass('Pluf_Form_BoundField'); // To get mb_ucfirst
|
||||
$defaults = array('required' => !$def['blank'],
|
||||
'label' => mb_ucfirst($def['verbose']),
|
||||
'help_text' => $def['help_text']);
|
||||
unset($def['blank'], $def['verbose'], $def['help_text']);
|
||||
if (isset($def['default'])) {
|
||||
$defaults['initial'] = $def['default'];
|
||||
unset($def['default']);
|
||||
}
|
||||
if (isset($def['choices'])) {
|
||||
$defaults['widget'] = 'Pluf_Form_Widget_SelectInput';
|
||||
if (isset($def['widget_attrs'])) {
|
||||
$def['widget_attrs']['choices'] = $def['choices'];
|
||||
} else {
|
||||
$def['widget_attrs'] = array('choices' => $def['choices']);
|
||||
}
|
||||
}
|
||||
foreach (array_keys($def) as $key) {
|
||||
if (!in_array($key, array('widget', 'label', 'required', 'multiple',
|
||||
'initial', 'choices', 'widget_attrs'))) {
|
||||
unset($def[$key]);
|
||||
}
|
||||
}
|
||||
$params = array_merge($defaults, $def);
|
||||
return new $form_field($params);
|
||||
}
|
||||
|
||||
}
|
||||
|
32
pluf/src/Pluf/DB/Field/Boolean.php
Normal file
32
pluf/src/Pluf/DB/Field/Boolean.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Boolean extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'boolean';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Boolean')
|
||||
{
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
42
pluf/src/Pluf/DB/Field/Compressed.php
Normal file
42
pluf/src/Pluf/DB/Field/Compressed.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* This field will automatically inflate/deflate its content.
|
||||
*
|
||||
* This can be used to store large text bodies where you do not need
|
||||
* to directly search into the content using the standard SQL
|
||||
* functions.
|
||||
*/
|
||||
class Pluf_DB_Field_Compressed extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'blob';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Varchar')
|
||||
{
|
||||
if (!isset($def['widget'])) {
|
||||
$def['widget'] = 'Pluf_Form_Widget_TextareaInput';
|
||||
}
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
32
pluf/src/Pluf/DB/Field/Date.php
Normal file
32
pluf/src/Pluf/DB/Field/Date.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Date extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'date';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Date')
|
||||
{
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
32
pluf/src/Pluf/DB/Field/Datetime.php
Normal file
32
pluf/src/Pluf/DB/Field/Datetime.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Datetime extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'datetime';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Datetime')
|
||||
{
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
33
pluf/src/Pluf/DB/Field/Email.php
Normal file
33
pluf/src/Pluf/DB/Field/Email.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Email extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'varchar';
|
||||
public $extra = array('size' => 200);
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Email')
|
||||
{
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
76
pluf/src/Pluf/DB/Field/File.php
Normal file
76
pluf/src/Pluf/DB/Field/File.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_File extends Pluf_DB_Field
|
||||
{
|
||||
/**
|
||||
* See definition in Pluf_DB_Field.
|
||||
*/
|
||||
public $type = 'file';
|
||||
public $column = '';
|
||||
public $value;
|
||||
public $extra = array();
|
||||
public $methods = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed Value ('')
|
||||
* @param string Column name ('')
|
||||
*/
|
||||
function __construct($value='', $column='', $extra=array())
|
||||
{
|
||||
parent::__construct($value, $column, $extra);
|
||||
$this->methods = array(array(strtolower($column).'_url', 'Pluf_DB_Field_File_Url'),
|
||||
array(strtolower($column).'_path', 'Pluf_DB_Field_File_Path')
|
||||
);
|
||||
}
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_File')
|
||||
{
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url to access the file.
|
||||
*/
|
||||
function Pluf_DB_Field_File_Url($field, $method, $model, $args=null)
|
||||
{
|
||||
if (strlen($model->$field) != 0) {
|
||||
return Pluf::f('upload_url').'/'.$model->$field;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to access the file.
|
||||
*/
|
||||
function Pluf_DB_Field_File_Path($field, $method, $model, $args=null)
|
||||
{
|
||||
if (strlen($model->$field) != 0) {
|
||||
return Pluf::f('upload_path').'/'.$model->$field;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
27
pluf/src/Pluf/DB/Field/Float.php
Normal file
27
pluf/src/Pluf/DB/Field/Float.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Float extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'float';
|
||||
}
|
38
pluf/src/Pluf/DB/Field/Foreignkey.php
Normal file
38
pluf/src/Pluf/DB/Field/Foreignkey.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Foreignkey extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'foreignkey';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Varchar')
|
||||
{
|
||||
$gmodel = new $def['model']();
|
||||
$choices = array();
|
||||
foreach ($gmodel->getList() as $item) {
|
||||
$choices[(string) $item] = $item->id;
|
||||
}
|
||||
$def['choices'] = $choices;
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
27
pluf/src/Pluf/DB/Field/Integer.php
Normal file
27
pluf/src/Pluf/DB/Field/Integer.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Integer extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'integer';
|
||||
}
|
45
pluf/src/Pluf/DB/Field/Manytomany.php
Normal file
45
pluf/src/Pluf/DB/Field/Manytomany.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Manytomany extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'manytomany';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Integer')
|
||||
{
|
||||
$method = 'get_'.$def['name'].'_list';
|
||||
$def['multiple'] = true;
|
||||
$def['initial'] = array();
|
||||
foreach ($def['model_instance']->$method() as $item) {
|
||||
$def['initial'][(string) $item] = $item->id;
|
||||
}
|
||||
$def['choices'] = array();
|
||||
foreach (Pluf::factory($def['model'])->getList() as $item) {
|
||||
$def['choices'][(string) $item] = $item->id;
|
||||
}
|
||||
if (!isset($def['widget'])) {
|
||||
$def['widget'] = 'Pluf_Form_Widget_SelectMultipleInput';
|
||||
}
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
33
pluf/src/Pluf/DB/Field/Password.php
Normal file
33
pluf/src/Pluf/DB/Field/Password.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Password extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'varchar';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Varchar')
|
||||
{
|
||||
$def['widget'] = 'Pluf_Form_Widget_PasswordInput';
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
36
pluf/src/Pluf/DB/Field/Sequence.php
Normal file
36
pluf/src/Pluf/DB/Field/Sequence.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Sequence extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'sequence';
|
||||
|
||||
/**
|
||||
* It is never possible to manually set the id of a model, this
|
||||
* should be passed through the URL.
|
||||
*/
|
||||
function formField($def, $form_field='')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
35
pluf/src/Pluf/DB/Field/Serialized.php
Normal file
35
pluf/src/Pluf/DB/Field/Serialized.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Serialized extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'text';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Varchar')
|
||||
{
|
||||
if (!isset($def['widget'])) {
|
||||
$def['widget'] = 'Pluf_Form_Widget_TextareaInput';
|
||||
}
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
71
pluf/src/Pluf/DB/Field/Slug.php
Normal file
71
pluf/src/Pluf/DB/Field/Slug.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* This field will automatically slugify its content.
|
||||
*
|
||||
* A slug is a short label for something, containing only letters,
|
||||
* numbers, underscores or hyphens. They're generally used in URLs.
|
||||
*
|
||||
* In your model, you can specify `max_length` in the `widget_attrs`
|
||||
* parameter. If `max_length` is not specified, Pluf will use a
|
||||
* default length of 50.
|
||||
*/
|
||||
class Pluf_DB_Field_Slug extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'varchar';
|
||||
|
||||
/**
|
||||
* @see Pluf_DB_Field::formField()
|
||||
*/
|
||||
function formField($def, $form_field = 'Pluf_Form_Field_Slug')
|
||||
{
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a "URL friendly" version in lowercase.
|
||||
*
|
||||
* Define the words separator with the configuration
|
||||
* option <code>slug-separator</code>. Default to <code>-</code>.
|
||||
*
|
||||
* @param $value string Value to convert
|
||||
* @return string The slugify version.
|
||||
*/
|
||||
public static function slugify($value)
|
||||
{
|
||||
$separator = Pluf::f('slug-separator', '-');
|
||||
$value = Pluf_Text_UTF8::romanize(Pluf_Text_UTF8::deaccent($value));
|
||||
$value = preg_replace('#[^'.$separator.'\w]#u',
|
||||
$separator,
|
||||
mb_strtolower($value, Pluf::f('encoding', 'UTF-8')));
|
||||
|
||||
// remove redundant
|
||||
$value = preg_replace('#'.$separator.'{2,}#u',
|
||||
$separator,
|
||||
trim($value, $separator));
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
35
pluf/src/Pluf/DB/Field/Text.php
Normal file
35
pluf/src/Pluf/DB/Field/Text.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Text extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'text';
|
||||
|
||||
function formField($def, $form_field='Pluf_Form_Field_Varchar')
|
||||
{
|
||||
if (!isset($def['widget'])) {
|
||||
$def['widget'] = 'Pluf_Form_Widget_TextareaInput';
|
||||
}
|
||||
return parent::formField($def, $form_field);
|
||||
}
|
||||
}
|
27
pluf/src/Pluf/DB/Field/Varchar.php
Normal file
27
pluf/src/Pluf/DB/Field/Varchar.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_Field_Varchar extends Pluf_DB_Field
|
||||
{
|
||||
public $type = 'varchar';
|
||||
}
|
52
pluf/src/Pluf/DB/Introspect.php
Normal file
52
pluf/src/Pluf/DB/Introspect.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
class Pluf_DB_Introspect
|
||||
{
|
||||
protected $int = null;
|
||||
protected $backend = '';
|
||||
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->int = Pluf::factory('Pluf_DB_Introspect_'.$db->engine, $db);
|
||||
$this->backend = $db->engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of tables in the current database. The search
|
||||
* automatically limit the list to the visible ones.
|
||||
*
|
||||
* @param object DB connection.
|
||||
* @return array List of tables.
|
||||
*/
|
||||
function listTables()
|
||||
{
|
||||
if (!method_exists($this->int, 'listTables')) {
|
||||
throw new Pluf_Exception_NotImplemented();
|
||||
}
|
||||
return $this->int->listTables();
|
||||
}
|
||||
}
|
||||
|
||||
|
50
pluf/src/Pluf/DB/Introspect/MySQL.php
Normal file
50
pluf/src/Pluf/DB/Introspect/MySQL.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
class Pluf_DB_Introspect_MySQL
|
||||
{
|
||||
protected $db = null;
|
||||
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of tables in the current database.
|
||||
*
|
||||
* @param object DB connection.
|
||||
* @return array List of tables.
|
||||
*/
|
||||
function listTables()
|
||||
{
|
||||
$sql = 'SHOW TABLES';
|
||||
$res = $this->db->select($sql);
|
||||
$tables = array();
|
||||
foreach ($res as $t) {
|
||||
$tables[] = array_pop($t);
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
}
|
56
pluf/src/Pluf/DB/Introspect/PostgreSQL.php
Normal file
56
pluf/src/Pluf/DB/Introspect/PostgreSQL.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
class Pluf_DB_Introspect_PostgreSQL
|
||||
{
|
||||
protected $db = null;
|
||||
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of tables in the current database. The search
|
||||
* automatically limit the list to the visible ones.
|
||||
*
|
||||
* @param object DB connection.
|
||||
* @return array List of tables.
|
||||
*/
|
||||
function listTables()
|
||||
{
|
||||
$sql = 'SELECT c.relname AS name
|
||||
FROM pg_catalog.pg_class c
|
||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind IN (\'r\', \'v\', \'\')
|
||||
AND n.nspname NOT IN (\'pg_catalog\', \'pg_toast\')
|
||||
AND pg_catalog.pg_table_is_visible(c.oid)';
|
||||
$res = $this->db->select($sql);
|
||||
$tables = array();
|
||||
foreach ($res as $t) {
|
||||
$tables[] = $t['name'];
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
}
|
202
pluf/src/Pluf/DB/MySQL.php
Normal file
202
pluf/src/Pluf/DB/MySQL.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* MySQL connection class
|
||||
*/
|
||||
class Pluf_DB_MySQL
|
||||
{
|
||||
public $con_id;
|
||||
public $pfx = '';
|
||||
private $debug = true;
|
||||
/** The last query, set with debug(). Used when an error is returned. */
|
||||
public $lastquery = '';
|
||||
public $engine = 'MySQL';
|
||||
public $type_cast = array();
|
||||
|
||||
function __construct($user, $pwd, $server, $dbname, $pfx='', $debug=false)
|
||||
{
|
||||
Pluf::loadFunction('Pluf_DB_defaultTypecast');
|
||||
$this->type_cast = Pluf_DB_defaultTypecast();
|
||||
$this->debug('* MYSQL CONNECT');
|
||||
$this->con_id = mysql_connect($server, $user, $pwd);
|
||||
$this->debug = $debug;
|
||||
$this->pfx = $pfx;
|
||||
if (!$this->con_id) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
$this->database($dbname);
|
||||
$this->execute('SET NAMES \'utf8\'');
|
||||
}
|
||||
|
||||
function database($dbname)
|
||||
{
|
||||
$db = mysql_select_db($dbname);
|
||||
$this->debug('* USE DATABASE '.$dbname);
|
||||
if (!$db) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the MySQL server.
|
||||
*
|
||||
* @return string Version string
|
||||
*/
|
||||
function getServerInfo()
|
||||
{
|
||||
return mysql_get_server_info($this->con_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the queries. Keep track of the last query and if in debug mode
|
||||
* keep track of all the queries in
|
||||
* $GLOBALS['_PX_debug_data']['sql_queries']
|
||||
*
|
||||
* @param string Query to keep track
|
||||
* @return bool true
|
||||
*/
|
||||
function debug($query)
|
||||
{
|
||||
$this->lastquery = $query;
|
||||
if (!$this->debug) return true;
|
||||
if (!isset($GLOBALS['_PX_debug_data']['sql_queries']))
|
||||
$GLOBALS['_PX_debug_data']['sql_queries'] = array();
|
||||
$GLOBALS['_PX_debug_data']['sql_queries'][] = $query;
|
||||
return true;
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
if ($this->con_id) {
|
||||
mysql_close($this->con_id);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function select($query)
|
||||
{
|
||||
$this->debug($query);
|
||||
$cur = mysql_query($query, $this->con_id);
|
||||
if ($cur) {
|
||||
$res = array();
|
||||
while ($row = mysql_fetch_assoc($cur)) {
|
||||
$res[] = $row;
|
||||
}
|
||||
mysql_free_result($cur);
|
||||
return $res;
|
||||
} else {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
}
|
||||
|
||||
function execute($query)
|
||||
{
|
||||
$this->debug($query);
|
||||
$cur = mysql_query($query, $this->con_id);
|
||||
if (!$cur) {
|
||||
throw new Exception($this->getError());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getLastID()
|
||||
{
|
||||
$this->debug('* GET LAST ID');
|
||||
return (int) mysql_insert_id($this->con_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string ready to be used in the exception.
|
||||
*
|
||||
* @return string Error string
|
||||
*/
|
||||
function getError()
|
||||
{
|
||||
|
||||
if ($this->con_id) {
|
||||
return mysql_errno($this->con_id).' - '
|
||||
.mysql_error($this->con_id).' - '.$this->lastquery;
|
||||
} else {
|
||||
return mysql_errno().' - '
|
||||
.mysql_error().' - '.$this->lastquery;
|
||||
}
|
||||
}
|
||||
|
||||
function esc($str)
|
||||
{
|
||||
return '\''.mysql_real_escape_string($str, $this->con_id).'\'';
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the column name.
|
||||
*
|
||||
* @param string Name of the column
|
||||
* @return string Escaped name
|
||||
*/
|
||||
function qn($col)
|
||||
{
|
||||
return '`'.$col.'`';
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction.
|
||||
*/
|
||||
function begin()
|
||||
{
|
||||
if (Pluf::f('db_mysql_transaction', false)) {
|
||||
$this->execute('BEGIN');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit a transaction.
|
||||
*/
|
||||
function commit()
|
||||
{
|
||||
if (Pluf::f('db_mysql_transaction', false)) {
|
||||
$this->execute('COMMIT');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback a transaction.
|
||||
*/
|
||||
function rollback()
|
||||
{
|
||||
if (Pluf::f('db_mysql_transaction', false)) {
|
||||
$this->execute('ROLLBACK');
|
||||
}
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return '<Pluf_DB_MySQL('.$this->con_id.')>';
|
||||
}
|
||||
|
||||
}
|
||||
|
271
pluf/src/Pluf/DB/PostgreSQL.php
Normal file
271
pluf/src/Pluf/DB/PostgreSQL.php
Normal file
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* PostgreSQL connection class
|
||||
*/
|
||||
class Pluf_DB_PostgreSQL
|
||||
{
|
||||
/**
|
||||
* The connection resource.
|
||||
*/
|
||||
public $con_id;
|
||||
|
||||
/**
|
||||
* The prefix for the table names.
|
||||
*/
|
||||
public $pfx = '';
|
||||
|
||||
/**
|
||||
* Debug mode.
|
||||
*/
|
||||
private $debug = false;
|
||||
|
||||
/**
|
||||
* The last query, set with debug(). Used when an error is
|
||||
* returned.
|
||||
*/
|
||||
public $lastquery = '';
|
||||
|
||||
/**
|
||||
* Name of the engine.
|
||||
*/
|
||||
public $engine = 'PostgreSQL';
|
||||
|
||||
/**
|
||||
* Used by the model to convert the values from and to the
|
||||
* database.
|
||||
*
|
||||
* @see Pluf_DB_defaultTypecast
|
||||
*/
|
||||
public $type_cast = array();
|
||||
|
||||
/**
|
||||
* Current query cursor.
|
||||
*/
|
||||
private $cur = null;
|
||||
|
||||
/**
|
||||
* Current search path.
|
||||
*/
|
||||
public $search_path = 'public';
|
||||
|
||||
function __construct($user, $pwd, $server, $dbname, $pfx='', $debug=false)
|
||||
{
|
||||
Pluf::loadFunction('Pluf_DB_defaultTypecast');
|
||||
$this->type_cast = Pluf_DB_defaultTypecast();
|
||||
$this->type_cast['Pluf_DB_Field_Boolean'] =
|
||||
array('Pluf_DB_PostgreSQL_BooleanFromDb', 'Pluf_DB_BooleanToDb');
|
||||
$this->type_cast['Pluf_DB_Field_Compressed'] =
|
||||
array('Pluf_DB_PostgreSQL_CompressedFromDb', 'Pluf_DB_PostgreSQL_CompressedToDb');
|
||||
|
||||
$this->debug('* POSTGRESQL CONNECT');
|
||||
$cstring = '';
|
||||
if ($server) {
|
||||
$cstring .= 'host='.$server.' ';
|
||||
}
|
||||
$cstring .= 'dbname='.$dbname.' user='.$user;
|
||||
if ($pwd) {
|
||||
$cstring .= ' password='.$pwd;
|
||||
}
|
||||
$this->debug = $debug;
|
||||
$this->pfx = $pfx;
|
||||
$this->cur = null;
|
||||
$this->con_id = @pg_connect($cstring);
|
||||
if (!$this->con_id) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the version of the PostgreSQL server.
|
||||
*
|
||||
* Requires PostgreSQL 7.4 or later.
|
||||
*
|
||||
* @return string Version string
|
||||
*/
|
||||
function getServerInfo()
|
||||
{
|
||||
$ver = pg_version($this->con_id);
|
||||
return $ver['server'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the queries. Keep track of the last query and if in debug mode
|
||||
* keep track of all the queries in
|
||||
* $GLOBALS['_PX_debug_data']['sql_queries']
|
||||
*
|
||||
* @param string Query to keep track
|
||||
* @return bool true
|
||||
*/
|
||||
function debug($query)
|
||||
{
|
||||
$this->lastquery = $query;
|
||||
if (!$this->debug) return true;
|
||||
if (!isset($GLOBALS['_PX_debug_data']['sql_queries']))
|
||||
$GLOBALS['_PX_debug_data']['sql_queries'] = array();
|
||||
$GLOBALS['_PX_debug_data']['sql_queries'][] = $query;
|
||||
return true;
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
if ($this->con_id) {
|
||||
pg_close($this->con_id);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function select($query)
|
||||
{
|
||||
$this->debug($query);
|
||||
$this->cur = @pg_query($this->con_id, $query);
|
||||
if (!$this->cur) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
$res = array();
|
||||
while ($row = pg_fetch_assoc($this->cur)) {
|
||||
$res[] = $row;
|
||||
}
|
||||
@pg_free_result($this->cur);
|
||||
$this->cur = null;
|
||||
return $res;
|
||||
}
|
||||
|
||||
function execute($query)
|
||||
{
|
||||
$this->debug($query);
|
||||
$this->cur = @pg_query($this->con_id, $query);
|
||||
if (!$this->cur) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getLastID()
|
||||
{
|
||||
$this->debug('* GET LAST ID');
|
||||
$res = $this->select('SELECT lastval() AS last_id');
|
||||
return (int) $res[0]['last_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string ready to be used in the exception.
|
||||
*
|
||||
* @return string Error string
|
||||
*/
|
||||
function getError()
|
||||
{
|
||||
if ($this->cur) {
|
||||
return pg_result_error($this->cur).' - '.$this->lastquery;
|
||||
}
|
||||
if ($this->con_id) {
|
||||
return pg_last_error($this->con_id).' - '.$this->lastquery;
|
||||
} else {
|
||||
return pg_last_error().' - '.$this->lastquery;
|
||||
}
|
||||
}
|
||||
|
||||
function esc($str)
|
||||
{
|
||||
return '\''.pg_escape_string($this->con_id, $str).'\'';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current search path.
|
||||
*/
|
||||
function setSearchPath($search_path='public')
|
||||
{
|
||||
if (preg_match('/[^\w\s\,]/', $search_path)) {
|
||||
throw new Exception('The search path: "'.$search_path.'" is not valid.');
|
||||
}
|
||||
$this->execute('SET search_path TO '.$search_path);
|
||||
$this->search_path = $search_path;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the column name.
|
||||
*
|
||||
* @param string Name of the column
|
||||
* @return string Escaped name
|
||||
*/
|
||||
function qn($col)
|
||||
{
|
||||
return '"'.$col.'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction.
|
||||
*/
|
||||
function begin()
|
||||
{
|
||||
$this->execute('BEGIN');
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit a transaction.
|
||||
*/
|
||||
function commit()
|
||||
{
|
||||
$this->execute('COMMIT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback a transaction.
|
||||
*/
|
||||
function rollback()
|
||||
{
|
||||
$this->execute('ROLLBACK');
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return '<Pluf_DB_PostgreSQL('.$this->con_id.')>';
|
||||
}
|
||||
}
|
||||
|
||||
function Pluf_DB_PostgreSQL_BooleanFromDb($val)
|
||||
{
|
||||
if (!$val) {
|
||||
return false;
|
||||
}
|
||||
return (strtolower(substr($val, 0, 1)) == 't');
|
||||
}
|
||||
|
||||
function Pluf_DB_PostgreSQL_CompressedToDb($val, $con)
|
||||
{
|
||||
if (is_null($val)) {
|
||||
return 'NULL';
|
||||
}
|
||||
return "'".pg_escape_bytea(gzdeflate($val, 9))."'";
|
||||
}
|
||||
|
||||
function Pluf_DB_PostgreSQL_CompressedFromDb($val)
|
||||
{
|
||||
return ($val) ? gzinflate(pg_unescape_bytea($val)) : $val;
|
||||
}
|
||||
|
178
pluf/src/Pluf/DB/SQLite.php
Normal file
178
pluf/src/Pluf/DB/SQLite.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* SQLite connection class
|
||||
*/
|
||||
class Pluf_DB_SQLite
|
||||
{
|
||||
public $con_id;
|
||||
public $pfx = '';
|
||||
private $debug = false;
|
||||
/** The last query, set with debug(). Used when an error is returned. */
|
||||
public $lastquery = '';
|
||||
public $engine = 'SQLite';
|
||||
public $type_cast = array();
|
||||
|
||||
function __construct($user, $pwd, $server, $dbname, $pfx='', $debug=false)
|
||||
{
|
||||
Pluf::loadFunction('Pluf_DB_defaultTypecast');
|
||||
$this->type_cast = Pluf_DB_defaultTypecast();
|
||||
$this->debug = $debug;
|
||||
$this->pfx = $pfx;
|
||||
$this->debug('* SQLITE OPEN');
|
||||
$this->type_cast['Pluf_DB_Field_Compressed'] = array('Pluf_DB_CompressedFromDb', 'Pluf_DB_SQLite_CompressedToDb');
|
||||
// Connect and let the Exception be thrown in case of problem
|
||||
try {
|
||||
$this->con_id = new PDO('sqlite:'.$dbname);
|
||||
} catch (PDOException $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the SQLite library.
|
||||
*
|
||||
* @return string Version string
|
||||
*/
|
||||
function getServerInfo()
|
||||
{
|
||||
return $this->con_id->getAttribute(PDO::ATTR_SERVER_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the queries. Keep track of the last query and if in debug mode
|
||||
* keep track of all the queries in
|
||||
* $GLOBALS['_PX_debug_data']['sql_queries']
|
||||
*
|
||||
* @param string Query to keep track
|
||||
* @return bool true
|
||||
*/
|
||||
function debug($query)
|
||||
{
|
||||
$this->lastquery = $query;
|
||||
if (!$this->debug) return true;
|
||||
if (!isset($GLOBALS['_PX_debug_data']['sql_queries']))
|
||||
$GLOBALS['_PX_debug_data']['sql_queries'] = array();
|
||||
$GLOBALS['_PX_debug_data']['sql_queries'][] = $query;
|
||||
return true;
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
$this->con_id = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
function select($query)
|
||||
{
|
||||
$this->debug($query);
|
||||
if (false === ($cur = $this->con_id->query($query))) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
return $cur->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function execute($query)
|
||||
{
|
||||
$this->debug($query);
|
||||
if (false === ($cur = $this->con_id->exec($query))) {
|
||||
throw new Exception($this->getError());
|
||||
}
|
||||
return $cur;
|
||||
|
||||
}
|
||||
|
||||
function getLastID()
|
||||
{
|
||||
$this->debug('* GET LAST ID');
|
||||
return (int) $this->con_id->lastInsertId();;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string ready to be used in the exception.
|
||||
*
|
||||
* @return string Error string
|
||||
*/
|
||||
function getError()
|
||||
{
|
||||
$err = $this->con_id->errorInfo();
|
||||
$err[] = $this->lastquery;
|
||||
return implode(' - ', $err);
|
||||
}
|
||||
|
||||
function esc($str)
|
||||
{
|
||||
return $this->con_id->quote($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the column name.
|
||||
*
|
||||
* @param string Name of the column
|
||||
* @return string Escaped name
|
||||
*/
|
||||
function qn($col)
|
||||
{
|
||||
return '"'.$col.'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction.
|
||||
*/
|
||||
function begin()
|
||||
{
|
||||
$this->execute('BEGIN');
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit a transaction.
|
||||
*/
|
||||
function commit()
|
||||
{
|
||||
$this->execute('COMMIT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback a transaction.
|
||||
*/
|
||||
function rollback()
|
||||
{
|
||||
$this->execute('ROLLBACK');
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return '<Pluf_DB_SQLite('.$this->con_id.')>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function Pluf_DB_SQLite_CompressedToDb($val, $con)
|
||||
{
|
||||
if (is_null($val)) {
|
||||
return 'NULL';
|
||||
}
|
||||
return 'X'.$con->esc(bin2hex(gzdeflate($val, 9)));
|
||||
}
|
156
pluf/src/Pluf/DB/Schema.php
Normal file
156
pluf/src/Pluf/DB/Schema.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Create the schema of a given Pluf_Model for a given database.
|
||||
*/
|
||||
class Pluf_DB_Schema
|
||||
{
|
||||
/**
|
||||
* Database connection object.
|
||||
*/
|
||||
private $con = null;
|
||||
|
||||
/**
|
||||
* Model from which the schema is generated.
|
||||
*/
|
||||
public $model = null;
|
||||
|
||||
/**
|
||||
* Schema generator object corresponding to the database.
|
||||
*/
|
||||
public $schema = null;
|
||||
|
||||
function __construct($db, $model=null)
|
||||
{
|
||||
$this->con = $db;
|
||||
$this->model = $model;
|
||||
$this->schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the schema generator.
|
||||
*
|
||||
* @return object Pluf_DB_Schema_XXXX
|
||||
*/
|
||||
function getGenerator()
|
||||
{
|
||||
return $this->schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the tables and indexes for the current model.
|
||||
*
|
||||
* @return mixed True if success or database error.
|
||||
*/
|
||||
function createTables()
|
||||
{
|
||||
$sql = $this->schema->getSqlCreate($this->model);
|
||||
foreach ($sql as $k => $query) {
|
||||
if (false === $this->con->execute($query)) {
|
||||
throw new Exception($this->con->getError());
|
||||
}
|
||||
}
|
||||
$sql = $this->schema->getSqlIndexes($this->model);
|
||||
foreach ($sql as $k => $query) {
|
||||
if (false === $this->con->execute($query)) {
|
||||
throw new Exception($this->con->getError());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the constraints for the current model.
|
||||
* This should be done _after_ all tables of all models have been created.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
function createConstraints()
|
||||
{
|
||||
$sql = $this->schema->getSqlCreateConstraints($this->model);
|
||||
foreach ($sql as $k => $query) {
|
||||
if (false === $this->con->execute($query)) {
|
||||
throw new Exception($this->con->getError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop the tables and indexes for the current model.
|
||||
*
|
||||
* @return mixed True if success or database error.
|
||||
*/
|
||||
function dropTables()
|
||||
{
|
||||
$sql = $this->schema->getSqlDelete($this->model);
|
||||
foreach ($sql as $k => $query) {
|
||||
if (false === $this->con->execute($query)) {
|
||||
throw new Exception($this->con->getError());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the constraints for the current model.
|
||||
* This should be done _before_ all tables of all models are dropped.
|
||||
*
|
||||
* @throws Exception
|
||||
* @return boolean
|
||||
*/
|
||||
function dropConstraints()
|
||||
{
|
||||
$sql = $this->schema->getSqlDeleteConstraints($this->model);
|
||||
foreach ($sql as $k => $query) {
|
||||
if (false === $this->con->execute($query)) {
|
||||
throw new Exception($this->con->getError());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a column name or a string with column names in the format
|
||||
* "column1, column2, column3", returns the escaped correctly
|
||||
* quoted column names. This is good for index creation.
|
||||
*
|
||||
* @param string Column
|
||||
* @param Pluf_DB DB handler
|
||||
* @return string Quoted for the DB column(s)
|
||||
*/
|
||||
public static function quoteColumn($col, $db)
|
||||
{
|
||||
if (false !== strpos($col, ',')) {
|
||||
$cols = explode(',', $col);
|
||||
} else {
|
||||
$cols = array($col);
|
||||
}
|
||||
$res = array();
|
||||
foreach ($cols as $col) {
|
||||
$res[] = $db->qn(trim($col));
|
||||
}
|
||||
return implode(', ', $res);
|
||||
}
|
||||
}
|
319
pluf/src/Pluf/DB/Schema/MySQL.php
Normal file
319
pluf/src/Pluf/DB/Schema/MySQL.php
Normal file
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Generator of the schemas corresponding to a given model.
|
||||
*
|
||||
* This class is for MySQL, you can create a class on the same
|
||||
* model for another database engine.
|
||||
*/
|
||||
class Pluf_DB_Schema_MySQL
|
||||
{
|
||||
/**
|
||||
* Mapping of the fields.
|
||||
*/
|
||||
public $mappings = array(
|
||||
'varchar' => 'varchar(%s)',
|
||||
'sequence' => 'mediumint(9) unsigned not null auto_increment',
|
||||
'boolean' => 'bool',
|
||||
'date' => 'date',
|
||||
'datetime' => 'datetime',
|
||||
'file' => 'varchar(150)',
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 'mediumint(9) unsigned',
|
||||
'text' => 'longtext',
|
||||
'html' => 'longtext',
|
||||
'time' => 'time',
|
||||
'integer' => 'integer',
|
||||
'email' => 'varchar(150)',
|
||||
'password' => 'varchar(150)',
|
||||
'float' => 'numeric(%s, %s)',
|
||||
'blob' => 'blob',
|
||||
);
|
||||
|
||||
public $defaults = array(
|
||||
'varchar' => "''",
|
||||
'sequence' => null,
|
||||
'boolean' => 1,
|
||||
'date' => 0,
|
||||
'datetime' => 0,
|
||||
'file' => "''",
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 0,
|
||||
'text' => "''",
|
||||
'html' => "''",
|
||||
'time' => 0,
|
||||
'integer' => 0,
|
||||
'email' => "''",
|
||||
'password' => "''",
|
||||
'float' => 0.0,
|
||||
'blob' => "''",
|
||||
);
|
||||
private $con = null;
|
||||
|
||||
function __construct($con)
|
||||
{
|
||||
$this->con = $con;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to generate the tables of the given model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlCreate($model)
|
||||
{
|
||||
$tables = array();
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
$sql = 'CREATE TABLE `'.$this->con->pfx.$model->_a['table'].'` (';
|
||||
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type != 'manytomany') {
|
||||
$sql .= "\n".$this->con->qn($col).' ';
|
||||
$_tmp = $this->mappings[$field->type];
|
||||
if ($field->type == 'varchar') {
|
||||
if (isset($val['size'])) {
|
||||
$_tmp = sprintf($this->mappings['varchar'], $val['size']);
|
||||
} else {
|
||||
$_tmp = sprintf($this->mappings['varchar'], '150');
|
||||
}
|
||||
}
|
||||
if ($field->type == 'float') {
|
||||
if (!isset($val['max_digits'])) {
|
||||
$val['max_digits'] = 32;
|
||||
}
|
||||
if (!isset($val['decimal_places'])) {
|
||||
$val['decimal_places'] = 8;
|
||||
}
|
||||
$_tmp = sprintf($this->mappings['float'], $val['max_digits'], $val['decimal_places']);
|
||||
}
|
||||
$sql .= $_tmp;
|
||||
if (empty($val['is_null'])) {
|
||||
$sql .= ' NOT NULL';
|
||||
}
|
||||
if (isset($val['default'])) {
|
||||
$sql .= ' default ';
|
||||
$sql .= $model->_toDb($val['default'], $col);
|
||||
} elseif ($field->type != 'sequence') {
|
||||
$sql .= ' default '.$this->defaults[$field->type];
|
||||
}
|
||||
$sql .= ',';
|
||||
} else {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
}
|
||||
$sql .= "\n".'PRIMARY KEY (`id`))';
|
||||
$sql .= 'ENGINE=InnoDB DEFAULT CHARSET=utf8;';
|
||||
$tables[$this->con->pfx.$model->_a['table']] = $sql;
|
||||
|
||||
// Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $hay[0].'_'.$hay[1].'_assoc';
|
||||
$sql = 'CREATE TABLE `'.$this->con->pfx.$table.'` (';
|
||||
$sql .= "\n".'`'.strtolower($model->_a['model']).'_id` '.$this->mappings['foreignkey'].' default 0,';
|
||||
$sql .= "\n".'`'.strtolower($omodel->_a['model']).'_id` '.$this->mappings['foreignkey'].' default 0,';
|
||||
$sql .= "\n".'PRIMARY KEY ('.strtolower($model->_a['model']).'_id, '.strtolower($omodel->_a['model']).'_id)';
|
||||
$sql .= "\n".') ENGINE=InnoDB';
|
||||
$sql .=' DEFAULT CHARSET=utf8;';
|
||||
$tables[$this->con->pfx.$table] = $sql;
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to generate the indexes of the given model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlIndexes($model)
|
||||
{
|
||||
$index = array();
|
||||
foreach ($model->_a['idx'] as $idx => $val) {
|
||||
if (!isset($val['col'])) {
|
||||
$val['col'] = $idx;
|
||||
}
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$idx] =
|
||||
sprintf('CREATE INDEX `%s` ON `%s` (%s);',
|
||||
$idx, $this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($val['col'], $this->con));
|
||||
}
|
||||
foreach ($model->_a['cols'] as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type == 'foreignkey') {
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$col.'_foreignkey'] =
|
||||
sprintf('CREATE INDEX `%s` ON `%s` (`%s`);',
|
||||
$col.'_foreignkey_idx', $this->con->pfx.$model->_a['table'], $col);
|
||||
}
|
||||
if (isset($val['unique']) and $val['unique'] == true) {
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$col.'_unique'] =
|
||||
sprintf('CREATE UNIQUE INDEX `%s` ON `%s` (%s);',
|
||||
$col.'_unique_idx',
|
||||
$this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($col, $this->con)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for <http://bugs.mysql.com/bug.php?id=13942> which limits the
|
||||
* length of foreign key identifiers to 64 characters.
|
||||
*
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function getShortenedFKeyName($name)
|
||||
{
|
||||
if (strlen($name) <= 64) {
|
||||
return $name;
|
||||
}
|
||||
return substr($name, 0, 55).'_'.substr(md5($name), 0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to create the constraints for the given model
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlCreateConstraints($model)
|
||||
{
|
||||
$table = $this->con->pfx.$model->_a['table'];
|
||||
$constraints = array();
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
// remember these for later
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
if ($field->type == 'foreignkey') {
|
||||
// Add the foreignkey constraints
|
||||
$referto = new $val['model']();
|
||||
$constraints[] = $alter_tbl.' ADD CONSTRAINT '.$this->getShortenedFKeyName($table.'_'.$col.'_fkey').'
|
||||
FOREIGN KEY ('.$this->con->qn($col).')
|
||||
REFERENCES '.$this->con->pfx.$referto->_a['table'].' (id)
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION';
|
||||
}
|
||||
}
|
||||
|
||||
// Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $this->con->pfx.$hay[0].'_'.$hay[1].'_assoc';
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$constraints[] = $alter_tbl.' ADD CONSTRAINT '.$this->getShortenedFKeyName($table.'_fkey1').'
|
||||
FOREIGN KEY ('.strtolower($model->_a['model']).'_id)
|
||||
REFERENCES '.$this->con->pfx.$model->_a['table'].' (id)
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION';
|
||||
$constraints[] = $alter_tbl.' ADD CONSTRAINT '.$this->getShortenedFKeyName($table.'_fkey2').'
|
||||
FOREIGN KEY ('.strtolower($omodel->_a['model']).'_id)
|
||||
REFERENCES '.$this->con->pfx.$omodel->_a['table'].' (id)
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION';
|
||||
}
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to drop the tables corresponding to the model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return string SQL string ready to execute.
|
||||
*/
|
||||
function getSqlDelete($model)
|
||||
{
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
$sql = 'DROP TABLE IF EXISTS `'.$this->con->pfx.$model->_a['table'].'`';
|
||||
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
}
|
||||
|
||||
//Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $hay[0].'_'.$hay[1].'_assoc';
|
||||
$sql .= ', `'.$this->con->pfx.$table.'`';
|
||||
}
|
||||
return array($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to drop the constraints for the given model
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlDeleteConstraints($model)
|
||||
{
|
||||
$table = $this->con->pfx.$model->_a['table'];
|
||||
$constraints = array();
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
// remember these for later
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
if ($field->type == 'foreignkey') {
|
||||
// Add the foreignkey constraints
|
||||
$referto = new $val['model']();
|
||||
$constraints[] = $alter_tbl.' DROP CONSTRAINT '.$this->getShortenedFKeyName($table.'_'.$col.'_fkey');
|
||||
}
|
||||
}
|
||||
|
||||
// Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $this->con->pfx.$hay[0].'_'.$hay[1].'_assoc';
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$constraints[] = $alter_tbl.' DROP CONSTRAINT '.$this->getShortenedFKeyName($table.'_fkey1');
|
||||
$constraints[] = $alter_tbl.' DROP CONSTRAINT '.$this->getShortenedFKeyName($table.'_fkey2');
|
||||
}
|
||||
return $constraints;
|
||||
}
|
||||
}
|
308
pluf/src/Pluf/DB/Schema/PostgreSQL.php
Normal file
308
pluf/src/Pluf/DB/Schema/PostgreSQL.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Generator of the schemas corresponding to a given model.
|
||||
*
|
||||
* This class is for PostgreSQL, you can create a class on the same
|
||||
* model for another database engine.
|
||||
*/
|
||||
class Pluf_DB_Schema_PostgreSQL
|
||||
|
||||
{
|
||||
/**
|
||||
* Mapping of the fields.
|
||||
*/
|
||||
public $mappings = array(
|
||||
'varchar' => 'character varying',
|
||||
'sequence' => 'serial',
|
||||
'boolean' => 'boolean',
|
||||
'date' => 'date',
|
||||
'datetime' => 'timestamp',
|
||||
'file' => 'character varying',
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 'integer',
|
||||
'text' => 'text',
|
||||
'html' => 'text',
|
||||
'time' => 'time',
|
||||
'integer' => 'integer',
|
||||
'email' => 'character varying',
|
||||
'password' => 'character varying',
|
||||
'float' => 'real',
|
||||
'blob' => 'bytea',
|
||||
);
|
||||
|
||||
public $defaults = array(
|
||||
'varchar' => "''",
|
||||
'sequence' => null,
|
||||
'boolean' => 'FALSE',
|
||||
'date' => "'0001-01-01'",
|
||||
'datetime' => "'0001-01-01 00:00:00'",
|
||||
'file' => "''",
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 0,
|
||||
'text' => "''",
|
||||
'html' => "''",
|
||||
'time' => "'00:00:00'",
|
||||
'integer' => 0,
|
||||
'email' => "''",
|
||||
'password' => "''",
|
||||
'float' => 0.0,
|
||||
'blob' => "''",
|
||||
|
||||
);
|
||||
private $con = null;
|
||||
|
||||
function __construct($con)
|
||||
{
|
||||
$this->con = $con;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the SQL to generate the tables of the given model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlCreate($model)
|
||||
{
|
||||
$tables = array();
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
$query = 'CREATE TABLE '.$this->con->pfx.$model->_a['table'].' (';
|
||||
$sql_col = array();
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type != 'manytomany') {
|
||||
$sql = $this->con->qn($col).' ';
|
||||
$sql .= $this->mappings[$field->type];
|
||||
if (empty($val['is_null'])) {
|
||||
$sql .= ' NOT NULL';
|
||||
}
|
||||
if (isset($val['default'])) {
|
||||
$sql .= ' default ';
|
||||
$sql .= $model->_toDb($val['default'], $col);
|
||||
} elseif ($field->type != 'sequence') {
|
||||
$sql .= ' default '.$this->defaults[$field->type];
|
||||
}
|
||||
$sql_col[] = $sql;
|
||||
} else {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
}
|
||||
$sql_col[] = 'CONSTRAINT '.$this->con->pfx.$model->_a['table'].'_pkey PRIMARY KEY (id)';
|
||||
$query = $query."\n".implode(",\n", $sql_col)."\n".');';
|
||||
$tables[$this->con->pfx.$model->_a['table']] = $query;
|
||||
// Now for the many to many
|
||||
// FIXME add index on the second column
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $hay[0].'_'.$hay[1].'_assoc';
|
||||
$sql = 'CREATE TABLE '.$this->con->pfx.$table.' (';
|
||||
$sql .= "\n".strtolower($model->_a['model']).'_id '.$this->mappings['foreignkey'].' default 0,';
|
||||
$sql .= "\n".strtolower($omodel->_a['model']).'_id '.$this->mappings['foreignkey'].' default 0,';
|
||||
$sql .= "\n".'CONSTRAINT '.$this->getShortenedIdentifierName($this->con->pfx.$table.'_pkey').' PRIMARY KEY ('.strtolower($model->_a['model']).'_id, '.strtolower($omodel->_a['model']).'_id)';
|
||||
$sql .= "\n".');';
|
||||
$tables[$this->con->pfx.$table] = $sql;
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to generate the indexes of the given model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlIndexes($model)
|
||||
{
|
||||
$index = array();
|
||||
foreach ($model->_a['idx'] as $idx => $val) {
|
||||
if (!isset($val['col'])) {
|
||||
$val['col'] = $idx;
|
||||
}
|
||||
if ($val['type'] == 'unique') {
|
||||
$unique = 'UNIQUE ';
|
||||
} else {
|
||||
$unique = '';
|
||||
}
|
||||
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$idx] =
|
||||
sprintf('CREATE '.$unique.'INDEX %s ON %s (%s);',
|
||||
$this->con->pfx.$model->_a['table'].'_'.$idx,
|
||||
$this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($val['col'], $this->con)
|
||||
);
|
||||
}
|
||||
foreach ($model->_a['cols'] as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if (isset($val['unique']) and $val['unique'] == true) {
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$col.'_unique'] =
|
||||
sprintf('CREATE UNIQUE INDEX %s ON %s (%s);',
|
||||
$this->con->pfx.$model->_a['table'].'_'.$col.'_unique_idx',
|
||||
$this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($col, $this->con)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* All identifiers in Postgres must not exceed 64 characters in length.
|
||||
*
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function getShortenedIdentifierName($name)
|
||||
{
|
||||
if (strlen($name) <= 64) {
|
||||
return $name;
|
||||
}
|
||||
return substr($name, 0, 55).'_'.substr(md5($name), 0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to create the constraints for the given model
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlCreateConstraints($model)
|
||||
{
|
||||
$table = $this->con->pfx.$model->_a['table'];
|
||||
$constraints = array();
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
// remember these for later
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
if ($field->type == 'foreignkey') {
|
||||
// Add the foreignkey constraints
|
||||
$referto = new $val['model']();
|
||||
$constraints[] = $alter_tbl.' ADD CONSTRAINT '.$this->getShortenedIdentifierName($table.'_'.$col.'_fkey').'
|
||||
FOREIGN KEY ('.$this->con->qn($col).')
|
||||
REFERENCES '.$this->con->pfx.$referto->_a['table'].' (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION';
|
||||
}
|
||||
}
|
||||
|
||||
// Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $this->con->pfx.$hay[0].'_'.$hay[1].'_assoc';
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$constraints[] = $alter_tbl.' ADD CONSTRAINT '.$this->getShortenedIdentifierName($table.'_fkey1').'
|
||||
FOREIGN KEY ('.strtolower($model->_a['model']).'_id)
|
||||
REFERENCES '.$this->con->pfx.$model->_a['table'].' (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION';
|
||||
$constraints[] = $alter_tbl.' ADD CONSTRAINT '.$this->getShortenedIdentifierName($table.'_fkey2').'
|
||||
FOREIGN KEY ('.strtolower($omodel->_a['model']).'_id)
|
||||
REFERENCES '.$this->con->pfx.$omodel->_a['table'].' (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION ON DELETE NO ACTION';
|
||||
}
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to drop the tables corresponding to the model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return string SQL string ready to execute.
|
||||
*/
|
||||
function getSqlDelete($model)
|
||||
{
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
$sql = array();
|
||||
$sql[] = 'DROP TABLE IF EXISTS '.$this->con->pfx.$model->_a['table'].' CASCADE';
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
}
|
||||
|
||||
//Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $hay[0].'_'.$hay[1].'_assoc';
|
||||
$sql[] = 'DROP TABLE IF EXISTS '.$this->con->pfx.$table.' CASCADE';
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to drop the constraints for the given model
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlDeleteConstraints($model)
|
||||
{
|
||||
$table = $this->con->pfx.$model->_a['table'];
|
||||
$constraints = array();
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
// remember these for later
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
if ($field->type == 'foreignkey') {
|
||||
// Add the foreignkey constraints
|
||||
$referto = new $val['model']();
|
||||
$constraints[] = $alter_tbl.' DROP CONSTRAINT '.$this->getShortenedIdentifierName($table.'_'.$col.'_fkey');
|
||||
}
|
||||
}
|
||||
|
||||
// Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $this->con->pfx.$hay[0].'_'.$hay[1].'_assoc';
|
||||
$alter_tbl = 'ALTER TABLE '.$table;
|
||||
$constraints[] = $alter_tbl.' DROP CONSTRAINT '.$this->getShortenedIdentifierName($table.'_fkey1');
|
||||
$constraints[] = $alter_tbl.' DROP CONSTRAINT '.$this->getShortenedIdentifierName($table.'_fkey2');
|
||||
}
|
||||
return $constraints;
|
||||
}
|
||||
}
|
||||
|
246
pluf/src/Pluf/DB/Schema/SQLite.php
Normal file
246
pluf/src/Pluf/DB/Schema/SQLite.php
Normal file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Generator of the schemas corresponding to a given model.
|
||||
*
|
||||
* This class is for SQLite, you can create a class on the same
|
||||
* model for another database engine.
|
||||
*/
|
||||
class Pluf_DB_Schema_SQLite
|
||||
|
||||
{
|
||||
/**
|
||||
* Mapping of the fields.
|
||||
*/
|
||||
public $mappings = array(
|
||||
'varchar' => 'varchar(%s)',
|
||||
'sequence' => 'integer primary key autoincrement',
|
||||
'boolean' => 'bool',
|
||||
'date' => 'date',
|
||||
'datetime' => 'datetime',
|
||||
'file' => 'varchar(150)',
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 'integer',
|
||||
'text' => 'text',
|
||||
'html' => 'text',
|
||||
'time' => 'time',
|
||||
'integer' => 'integer',
|
||||
'email' => 'varchar(150)',
|
||||
'password' => 'varchar(150)',
|
||||
'float' => 'real',
|
||||
'blob' => 'blob',
|
||||
);
|
||||
|
||||
public $defaults = array(
|
||||
'varchar' => "''",
|
||||
'sequence' => null,
|
||||
'boolean' => 1,
|
||||
'date' => 0,
|
||||
'datetime' => 0,
|
||||
'file' => "''",
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 0,
|
||||
'text' => "''",
|
||||
'html' => "''",
|
||||
'time' => 0,
|
||||
'integer' => 0,
|
||||
'email' => "''",
|
||||
'password' => "''",
|
||||
'float' => 0.0,
|
||||
'blob' => "''",
|
||||
);
|
||||
private $con = null;
|
||||
|
||||
function __construct($con)
|
||||
{
|
||||
$this->con = $con;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the SQL to generate the tables of the given model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlCreate($model)
|
||||
{
|
||||
$tables = array();
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
$query = 'CREATE TABLE '.$this->con->pfx.$model->_a['table'].' (';
|
||||
$sql_col = array();
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type != 'manytomany') {
|
||||
$sql = $this->con->qn($col).' ';
|
||||
$_tmp = $this->mappings[$field->type];
|
||||
if ($field->type == 'varchar') {
|
||||
if (isset($val['size'])) {
|
||||
$_tmp = sprintf($this->mappings['varchar'], $val['size']);
|
||||
} else {
|
||||
$_tmp = sprintf($this->mappings['varchar'], '150');
|
||||
}
|
||||
}
|
||||
if ($field->type == 'float') {
|
||||
if (!isset($val['max_digits'])) {
|
||||
$val['max_digits'] = 32;
|
||||
}
|
||||
if (!isset($val['decimal_places'])) {
|
||||
$val['decimal_places'] = 8;
|
||||
}
|
||||
$_tmp = sprintf($this->mappings['float'], $val['max_digits'], $val['decimal_places']);
|
||||
}
|
||||
$sql .= $_tmp;
|
||||
if (empty($val['is_null'])) {
|
||||
$sql .= ' not null';
|
||||
}
|
||||
if (isset($val['default'])) {
|
||||
$sql .= ' default '.$model->_toDb($val['default'], $col);
|
||||
} elseif ($field->type != 'sequence') {
|
||||
$sql .= ' default '.$this->defaults[$field->type];
|
||||
}
|
||||
$sql_col[] = $sql;
|
||||
} else {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
}
|
||||
$query = $query."\n".implode(",\n", $sql_col)."\n".');';
|
||||
$tables[$this->con->pfx.$model->_a['table']] = $query;
|
||||
|
||||
//Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $hay[0].'_'.$hay[1].'_assoc';
|
||||
$sql = 'CREATE TABLE '.$this->con->pfx.$table.' (';
|
||||
$sql .= "\n".strtolower($model->_a['model']).'_id '.$this->mappings['foreignkey'].' default 0,';
|
||||
$sql .= "\n".strtolower($omodel->_a['model']).'_id '.$this->mappings['foreignkey'].' default 0,';
|
||||
$sql .= "\n".'primary key ('.strtolower($model->_a['model']).'_id, '.strtolower($omodel->_a['model']).'_id)';
|
||||
$sql .= "\n".');';
|
||||
$tables[$this->con->pfx.$table] = $sql;
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQLite cannot add foreign key constraints to already existing tables,
|
||||
* so we skip their creation completely.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array
|
||||
*/
|
||||
function getSqlCreateConstraints($model)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to generate the indexes of the given model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array Array of SQL strings ready to execute.
|
||||
*/
|
||||
function getSqlIndexes($model)
|
||||
{
|
||||
$index = array();
|
||||
foreach ($model->_a['idx'] as $idx => $val) {
|
||||
if (!isset($val['col'])) {
|
||||
$val['col'] = $idx;
|
||||
}
|
||||
$unique = (isset($val['type']) && ($val['type'] == 'unique')) ? 'UNIQUE ' : '';
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$idx] =
|
||||
sprintf('CREATE %sINDEX %s ON %s (%s);',
|
||||
$unique,
|
||||
$this->con->pfx.$model->_a['table'].'_'.$idx,
|
||||
$this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($val['col'], $this->con)
|
||||
);
|
||||
}
|
||||
foreach ($model->_a['cols'] as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type == 'foreignkey') {
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$col.'_foreignkey'] =
|
||||
sprintf('CREATE INDEX %s ON %s (%s);',
|
||||
$this->con->pfx.$model->_a['table'].'_'.$col.'_foreignkey_idx',
|
||||
$this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($col, $this->con));
|
||||
}
|
||||
if (isset($val['unique']) and $val['unique'] == true) {
|
||||
$index[$this->con->pfx.$model->_a['table'].'_'.$col.'_unique'] =
|
||||
sprintf('CREATE UNIQUE INDEX %s ON %s (%s);',
|
||||
$this->con->pfx.$model->_a['table'].'_'.$col.'_unique_idx',
|
||||
$this->con->pfx.$model->_a['table'],
|
||||
Pluf_DB_Schema::quoteColumn($col, $this->con)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to drop the tables corresponding to the model.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return string SQL string ready to execute.
|
||||
*/
|
||||
function getSqlDelete($model)
|
||||
{
|
||||
$cols = $model->_a['cols'];
|
||||
$manytomany = array();
|
||||
$sql = array();
|
||||
$sql[] = 'DROP TABLE IF EXISTS '.$this->con->pfx.$model->_a['table'];
|
||||
foreach ($cols as $col => $val) {
|
||||
$field = new $val['type']();
|
||||
if ($field->type == 'manytomany') {
|
||||
$manytomany[] = $col;
|
||||
}
|
||||
}
|
||||
|
||||
//Now for the many to many
|
||||
foreach ($manytomany as $many) {
|
||||
$omodel = new $cols[$many]['model']();
|
||||
$hay = array(strtolower($model->_a['model']), strtolower($omodel->_a['model']));
|
||||
sort($hay);
|
||||
$table = $hay[0].'_'.$hay[1].'_assoc';
|
||||
$sql[] = 'DROP TABLE IF EXISTS '.$this->con->pfx.$table;
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQLite cannot drop foreign keys from existing tables,
|
||||
* so we skip their deletion completely.
|
||||
*
|
||||
* @param Object Model
|
||||
* @return array
|
||||
*/
|
||||
function getSqlDeleteConstraints($model)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
53
pluf/src/Pluf/DB/SchemaInfo.php
Normal file
53
pluf/src/Pluf/DB/SchemaInfo.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_DB_SchemaInfo extends Pluf_Model
|
||||
{
|
||||
public $_model = __CLASS__;
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->_a['table'] = 'schema_info';
|
||||
$this->_a['model'] = 'Pluf_DB_SchemaInfo';
|
||||
$this->_a['cols'] = array(
|
||||
// It is mandatory to have an "id" column.
|
||||
'id' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Sequence',
|
||||
//It is automatically added.
|
||||
'blank' => true,
|
||||
),
|
||||
'application' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Varchar',
|
||||
'blank' => false,
|
||||
'unique' => true,
|
||||
),
|
||||
'version' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Integer',
|
||||
'blank' => false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
84
pluf/src/Pluf/DB/Stats.php
Normal file
84
pluf/src/Pluf/DB/Stats.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Database statistics class.
|
||||
*
|
||||
* This class is just a wrapper which will pass the queries to the
|
||||
* underlying database class but keeping timing information. This is
|
||||
* very good to track your slow queries and improve your code.
|
||||
*
|
||||
*/
|
||||
class Pluf_DB_Stats
|
||||
{
|
||||
/**
|
||||
* The real database connection.
|
||||
*/
|
||||
protected $_rdb = null;
|
||||
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->_rdb = $db;
|
||||
}
|
||||
|
||||
public function __call($name, $args)
|
||||
{
|
||||
if (!in_array($name, array('execute', 'select'))) {
|
||||
return call_user_func_array(array($this->_rdb, $name), $args);
|
||||
}
|
||||
Pluf_Log::stime('timer');
|
||||
$res = call_user_func_array(array($this->_rdb, $name), $args);
|
||||
Pluf_Log::perf(array('Pluf_DB_Stats', $this->_rdb->lastquery, Pluf_Log::etime('timer', 'total_sql')));
|
||||
Pluf_Log::inc('sql_query');
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->_rdb->$name;
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
return $this->_rdb->$name = $value;
|
||||
}
|
||||
}
|
||||
|
||||
function Pluf_DB_Stats_getConnection($extra=null)
|
||||
{
|
||||
if (isset($GLOBALS['_PX_db']) &&
|
||||
(is_resource($GLOBALS['_PX_db']->con_id) or is_object($GLOBALS['_PX_db']->con_id))) {
|
||||
return $GLOBALS['_PX_db'];
|
||||
}
|
||||
$GLOBALS['_PX_db'] = new Pluf_DB_Stats(
|
||||
Pluf_DB::get(Pluf::f('db_engine'),
|
||||
Pluf::f('db_server'),
|
||||
Pluf::f('db_database'),
|
||||
Pluf::f('db_login'),
|
||||
Pluf::f('db_password'),
|
||||
Pluf::f('db_table_prefix'),
|
||||
Pluf::f('db_debug'),
|
||||
Pluf::f('db_version'))
|
||||
);
|
||||
return $GLOBALS['_PX_db'];
|
||||
}
|
212
pluf/src/Pluf/Date.php
Normal file
212
pluf/src/Pluf/Date.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
class Pluf_Date
|
||||
{
|
||||
/**
|
||||
* Get a GM Date in the format YYYY-MM-DD HH:MM:SS and returns a
|
||||
* string with the given format in the current timezone.
|
||||
*
|
||||
* @param string GMDate
|
||||
* @param string Format to be given to strftime ('%Y-%m-%d %H:%M:%S')
|
||||
* @return string Formated GMDate into the local time
|
||||
*/
|
||||
public static function gmDateToString($gmdate, $format='%Y-%m-%d %H:%M:%S')
|
||||
{
|
||||
$time = strtotime($gmdate.'Z');
|
||||
return strftime($format, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a GM Date in the format YYYY-MM-DD HH:MM:SS and returns a
|
||||
* string with the given format in GMT.
|
||||
*
|
||||
* @param string GMDate
|
||||
* @param string Format to be given to date ('c')
|
||||
* @return string Formated GMDate into GMT
|
||||
*/
|
||||
public static function gmDateToGmString($gmdate, $format='c')
|
||||
{
|
||||
$time = strtotime($gmdate.'Z');
|
||||
return date($format, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Day compare.
|
||||
*
|
||||
* Compare if the first date is before or after the second date.
|
||||
* Returns:
|
||||
* 0 if the days are the same.
|
||||
* 1 if the first date is before the second.
|
||||
* -1 if the first date is after the second.
|
||||
*
|
||||
* @param string YYYY-MM-DD date.
|
||||
* @param string YYYY-MM-DD date (today local time).
|
||||
* @return int
|
||||
*/
|
||||
public static function dayCompare($date1, $date2=null)
|
||||
{
|
||||
$date2 = (is_null($date2)) ? date('Y-m-d') : $date2;
|
||||
if ($date2 == $date1) return 0;
|
||||
if ($date1 > $date2) return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of functions to manage dates.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compare two date and returns the number of seconds between the
|
||||
* first and the second. If only the date is given without time, the
|
||||
* end of the day is used (23:59:59).
|
||||
*
|
||||
* @param string Date to compare for ex: '2006-09-17 18:42:00'
|
||||
* @param string Second date to compare if null use now (null)
|
||||
* @return int Number of seconds between the two dates. Negative
|
||||
* value if the second date is before the first.
|
||||
*/
|
||||
function Pluf_Date_Compare($date1, $date2=null)
|
||||
{
|
||||
if (strlen($date1) == 10) {
|
||||
$date1 .= ' 23:59:59';
|
||||
}
|
||||
if (is_null($date2)) {
|
||||
$date2 = time();
|
||||
} else {
|
||||
if (strlen($date2) == 10) {
|
||||
$date2 .= ' 23:59:59';
|
||||
}
|
||||
$date2 = strtotime(str_replace('-', '/', $date2));
|
||||
}
|
||||
$date1 = strtotime(str_replace('-', '/', $date1));
|
||||
return $date2 - $date1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a date in the format:
|
||||
* X days Y hours ago
|
||||
* X hours Y minutes ago
|
||||
* X hours Y minutes left
|
||||
*
|
||||
* "resolution" is year, month, day, hour, minute.
|
||||
*
|
||||
* If not time is given, only the day, the end of the day is
|
||||
* used: 23:59:59.
|
||||
*
|
||||
* @param string Date to compare with ex: '2006-09-17 18:42:00'
|
||||
* @param string Reference date to compare with by default now (null)
|
||||
* @param int Maximum number of elements to show (2)
|
||||
* @param string If no delay between the two dates display ('now')
|
||||
* @param bool Show ago/left suffix
|
||||
* @return string Formatted date
|
||||
*/
|
||||
function Pluf_Date_Easy($date, $ref=null, $blocks=2, $notime='now', $show=true)
|
||||
{
|
||||
if (strlen($date) == 10) {
|
||||
$date .= ' 23:59:59';
|
||||
}
|
||||
if (is_null($ref)) {
|
||||
$ref = date('Y-m-d H:i:s');
|
||||
$tref = time();
|
||||
} else {
|
||||
if (strlen($ref) == 10) {
|
||||
$ref .= ' 23:59:59';
|
||||
}
|
||||
$tref = strtotime(str_replace('-', '/', $ref));
|
||||
}
|
||||
$tdate = strtotime(str_replace('-', '/', $date));
|
||||
$past = true;
|
||||
if ($tref < $tdate) {
|
||||
// date in the past
|
||||
$past = false;
|
||||
$_tmp = $ref;
|
||||
$ref = $date;
|
||||
$date = $_tmp;
|
||||
}
|
||||
$ref = str_replace(array(' ', ':'), '-', $ref);
|
||||
$date = str_replace(array(' ', ':'), '-', $date);
|
||||
$refs = explode('-', $ref);
|
||||
$dates = explode('-', $date);
|
||||
// Modulo on the month is dynamically calculated after
|
||||
$modulos = array(365, 12, 31, 24, 60, 60);
|
||||
// day in month
|
||||
$month = $refs[1] - 1;
|
||||
$modulos[2] = date('t', mktime(0, 0, 0, $month, 1, $refs[0]));
|
||||
$diffs = array();
|
||||
for ($i=0; $i<6; $i++) {
|
||||
$diffs[$i] = $refs[$i] - $dates[$i];
|
||||
}
|
||||
$retain = 0;
|
||||
for ($i=5; $i>-1; $i--) {
|
||||
$diffs[$i] = $diffs[$i] - $retain;
|
||||
$retain = 0;
|
||||
if ($diffs[$i] < 0) {
|
||||
$diffs[$i] = $modulos[$i] + $diffs[$i];
|
||||
$retain = 1;
|
||||
}
|
||||
}
|
||||
$res = '';
|
||||
$total = 0;
|
||||
for ($i=0; $i<5; $i++) {
|
||||
if ($diffs[$i] > 0) {
|
||||
$total++;
|
||||
$res .= $diffs[$i].' ';
|
||||
switch ($i) {
|
||||
case 0:
|
||||
$res .= _n('year', 'years', $diffs[$i]);
|
||||
break;
|
||||
case 1:
|
||||
$res .= _n('month', 'months', $diffs[$i]);
|
||||
break;
|
||||
case 2:
|
||||
$res .= _n('day', 'days', $diffs[$i]);
|
||||
break;
|
||||
case 3:
|
||||
$res .= _n('hour', 'hours', $diffs[$i]);
|
||||
break;
|
||||
case 4:
|
||||
$res .= _n('minute', 'minutes', $diffs[$i]);
|
||||
break;
|
||||
case 5:
|
||||
$res .= _n('second', 'seconds', $diffs[$i]);
|
||||
break;
|
||||
}
|
||||
$res .= ' ';
|
||||
}
|
||||
if ($total >= $blocks) break;
|
||||
}
|
||||
if (strlen($res) == 0) {
|
||||
return $notime;
|
||||
}
|
||||
if ($show) {
|
||||
if ($past) {
|
||||
$res = sprintf(__('%s ago'), $res);
|
||||
} else {
|
||||
$res = sprintf(__('%s left'), $res);
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
223
pluf/src/Pluf/Dispatcher.php
Normal file
223
pluf/src/Pluf/Dispatcher.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Dispatcher
|
||||
{
|
||||
/**
|
||||
* The unique method to call.
|
||||
*
|
||||
* @param string Query string ('')
|
||||
*/
|
||||
public static function dispatch($query='')
|
||||
{
|
||||
try {
|
||||
$query = preg_replace('#^(/)+#', '/', '/'.$query);
|
||||
$req = new Pluf_HTTP_Request($query);
|
||||
$middleware = array();
|
||||
foreach (Pluf::f('middleware_classes', array()) as $mw) {
|
||||
$middleware[] = new $mw();
|
||||
}
|
||||
$skip = false;
|
||||
foreach ($middleware as $mw) {
|
||||
if (method_exists($mw, 'process_request')) {
|
||||
$response = $mw->process_request($req);
|
||||
if ($response !== false) {
|
||||
// $response is a response
|
||||
if (Pluf::f('pluf_runtime_header', false)) {
|
||||
$response->headers['X-Perf-Runtime'] = sprintf('%.5f', (microtime(true) - $GLOBALS['_PX_starttime']));
|
||||
}
|
||||
$response->render($req->method != 'HEAD' and !defined('IN_UNIT_TESTS'));
|
||||
$skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($skip === false) {
|
||||
$response = self::match($req);
|
||||
if (!empty($req->response_vary_on)) {
|
||||
$response->headers['Vary'] = $req->response_vary_on;
|
||||
}
|
||||
$middleware = array_reverse($middleware);
|
||||
foreach ($middleware as $mw) {
|
||||
if (method_exists($mw, 'process_response')) {
|
||||
$response = $mw->process_response($req, $response);
|
||||
}
|
||||
}
|
||||
if (Pluf::f('pluf_runtime_header', false)) {
|
||||
$response->headers['X-Perf-Runtime'] = sprintf('%.5f', (microtime(true) - $GLOBALS['_PX_starttime']));
|
||||
}
|
||||
$response->render($req->method != 'HEAD' and !defined('IN_UNIT_TESTS'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
if (Pluf::f('debug', false) == true) {
|
||||
$response = new Pluf_HTTP_Response_ServerErrorDebug($e);
|
||||
} else {
|
||||
$response = new Pluf_HTTP_Response_ServerError($e);
|
||||
}
|
||||
$response->render($req->method != 'HEAD' and !defined('IN_UNIT_TESTS'));
|
||||
if (defined('IN_UNIT_TESTS')) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* [signal]
|
||||
*
|
||||
* Pluf_Dispatcher::postDispatch
|
||||
*
|
||||
* [sender]
|
||||
*
|
||||
* Pluf_Dispatcher
|
||||
*
|
||||
* [description]
|
||||
*
|
||||
* This signal is sent after the rendering of a request. This
|
||||
* means you cannot affect the response but you can use this
|
||||
* hook to do some cleaning.
|
||||
*
|
||||
* [parameters]
|
||||
*
|
||||
* array('request' => $request,
|
||||
* 'response' => $response)
|
||||
*
|
||||
*/
|
||||
$params = array('request' => $req,
|
||||
'response' => $response);
|
||||
Pluf_Signal::send('Pluf_Dispatcher::postDispatch',
|
||||
'Pluf_Dispatcher', $params);
|
||||
return array($req, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match a query against the actions controllers.
|
||||
*
|
||||
* @see Pluf_HTTP_URL_reverse
|
||||
*
|
||||
* @param Pluf_HTTP_Request Request object
|
||||
* @return Pluf_HTTP_Response Response object
|
||||
*/
|
||||
public static function match($req, $firstpass=true)
|
||||
{
|
||||
try {
|
||||
$views = $GLOBALS['_PX_views'];
|
||||
$to_match = $req->query;
|
||||
$n = count($views);
|
||||
$i = 0;
|
||||
while ($i<$n) {
|
||||
$ctl = $views[$i];
|
||||
if (preg_match($ctl['regex'], $to_match, $match)) {
|
||||
if (!isset($ctl['sub'])) {
|
||||
return self::send($req, $ctl, $match);
|
||||
} else {
|
||||
// Go in the subtree
|
||||
$views = $ctl['sub'];
|
||||
$i = 0;
|
||||
$n = count($views);
|
||||
$to_match = substr($to_match, strlen($match[0]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
} catch (Pluf_HTTP_Error404 $e) {
|
||||
// Need to add a 404 error handler
|
||||
// something like Pluf::f('404_handler', 'class::method')
|
||||
}
|
||||
if ($firstpass and substr($req->query, -1) != '/') {
|
||||
$req->query .= '/';
|
||||
$res = self::match($req, false);
|
||||
if ($res->status_code != 404) {
|
||||
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
|
||||
$name = (isset($req->view[0]['name'])) ?
|
||||
$req->view[0]['name'] :
|
||||
$req->view[0]['model'].'::'.$req->view[0]['method'];
|
||||
$url = Pluf_HTTP_URL_urlForView($name, array_slice($req->view[1], 1));
|
||||
return new Pluf_HTTP_Response_Redirect($url, 301);
|
||||
}
|
||||
}
|
||||
return new Pluf_HTTP_Response_NotFound($req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the view found by self::match.
|
||||
*
|
||||
* The called view can throw an exception. This is fine and
|
||||
* normal.
|
||||
*
|
||||
* @param Pluf_HTTP_Request Current request
|
||||
* @param array The url definition matching the request
|
||||
* @param array The match found by preg_match
|
||||
* @return Pluf_HTTP_Response Response object
|
||||
*/
|
||||
public static function send($req, $ctl, $match)
|
||||
{
|
||||
$req->view = array($ctl, $match);
|
||||
$m = new $ctl['model']();
|
||||
if (isset($m->{$ctl['method'].'_precond'})) {
|
||||
// Here we have preconditions to respects. If the "answer"
|
||||
// is true, then ok go ahead, if not then it a response so
|
||||
// return it or an exception so let it go.
|
||||
$preconds = $m->{$ctl['method'].'_precond'};
|
||||
if (!is_array($preconds)) {
|
||||
$preconds = array($preconds);
|
||||
}
|
||||
foreach ($preconds as $precond) {
|
||||
if (!is_array($precond)) {
|
||||
$res = call_user_func_array(
|
||||
explode('::', $precond),
|
||||
array(&$req)
|
||||
);
|
||||
} else {
|
||||
$res = call_user_func_array(
|
||||
explode('::', $precond[0]),
|
||||
array_merge(array(&$req),
|
||||
array_slice($precond, 1))
|
||||
);
|
||||
}
|
||||
if ($res !== true) {
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset($ctl['params'])) {
|
||||
return $m->$ctl['method']($req, $match);
|
||||
} else {
|
||||
return $m->$ctl['method']($req, $match, $ctl['params']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the controllers.
|
||||
*
|
||||
* @param string File including the views.
|
||||
* @return bool Success.
|
||||
*/
|
||||
public static function loadControllers($file)
|
||||
{
|
||||
if (file_exists($file)) {
|
||||
$GLOBALS['_PX_views'] = include $file;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
186
pluf/src/Pluf/Encoder.php
Normal file
186
pluf/src/Pluf/Encoder.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Validators are functions used to validate user/program input.
|
||||
*
|
||||
* A validator signature is:
|
||||
* my_validator($field_data, $params=array())
|
||||
* with $params an associative array of parameters.
|
||||
*
|
||||
*
|
||||
* A validator must fail on an empty string by raising an
|
||||
* Pluf_Form_Invalid Exception or return the data in the right format
|
||||
* (string, bool, whatever).
|
||||
*
|
||||
* FIXME: Escape the strings when bad strings are sent in the error message.
|
||||
*/
|
||||
class Pluf_Encoder
|
||||
{
|
||||
/**
|
||||
* Store the complete form data if validation is coming from a form.
|
||||
*/
|
||||
protected $form = array();
|
||||
|
||||
/**
|
||||
* Set the form data.
|
||||
*
|
||||
* @param &array Reference to the form data
|
||||
*/
|
||||
function setFormData(&$form)
|
||||
{
|
||||
$this->form = $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if could be empty or not.
|
||||
*/
|
||||
function checkEmpty($data, $form=array(), $p=array())
|
||||
{
|
||||
if (strlen($data) == 0
|
||||
and isset($p['blank']) and false == $p['blank']) {
|
||||
throw new Pluf_Form_Invalid(__('The value must not be empty.'));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate an url.
|
||||
* Only the structure is checked, no check of availability of the
|
||||
* url is performed. It is a really basic validation.
|
||||
*/
|
||||
static function url($url, $form=array(), $p=array())
|
||||
{
|
||||
$ip = '(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.'
|
||||
.'(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}';
|
||||
$dom = '([a-z0-9\.\-]+)';
|
||||
if (preg_match('!^(http|https|ftp|gopher)\://('.$ip.'|'.$dom.')!i', $url)) {
|
||||
return $url;
|
||||
} else {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The URL <em>%s</em> is not valid.'), htmlspecialchars($url)));
|
||||
}
|
||||
}
|
||||
|
||||
static function varchar($string, $form=array(), $p=array())
|
||||
{
|
||||
if (isset($p['size']) && strlen($string) > $p['size']) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The value should not be more than <em>%s</em> characters long.'), $p['size']));
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
static function password($string, $form=array(), $p=array())
|
||||
{
|
||||
if (strlen($string) < 6) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The password must be at least <em>%s</em> characters long.'), '6'));
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
static function email($string, $form=array(), $p=array())
|
||||
{
|
||||
if (preg_match('/^[A-Z0-9._%-][+A-Z0-9._%-]*@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i', $string)) {
|
||||
return $string;
|
||||
} else {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The email address "%s" is not valid.'),
|
||||
$string));
|
||||
}
|
||||
}
|
||||
|
||||
static function text($string, $form=array(), $p=array())
|
||||
{
|
||||
return Pluf_Encoder::varchar($string, $form, $p);
|
||||
}
|
||||
|
||||
|
||||
static function sequence($id, $form=array(), $p=array())
|
||||
{
|
||||
return Pluf_Encoder::integer($id, $p);
|
||||
}
|
||||
|
||||
static function boolean($bool, $form=array(), $p=array())
|
||||
{
|
||||
if (in_array($bool, array('on', 'y', '1', 1, true))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function foreignkey($id, $form=array(), $p=array())
|
||||
{
|
||||
return Pluf_Encoder::integer($id, $p);
|
||||
}
|
||||
|
||||
static function integer($int, $form=array(), $p=array())
|
||||
{
|
||||
if (!preg_match('/[0-9]+/', $int)) {
|
||||
throw new Pluf_Form_Invalid(__('The value must be an integer.'));
|
||||
}
|
||||
return (int) $int;
|
||||
}
|
||||
|
||||
static function datetime($datetime, $form=array(), $p=array())
|
||||
{
|
||||
if (false === ($stamp = strtotime($datetime))) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The date and time <em>%s</em> are not valid.'), htmlspecialchars($datetime)));
|
||||
}
|
||||
//convert to GMT
|
||||
return gmdate('Y-m-d H:i:s', $stamp);
|
||||
}
|
||||
|
||||
static function date($date, $form=array(), $p=array())
|
||||
{
|
||||
$ymd = explode('-', $date);
|
||||
if (count($ymd) != 3 or strlen($ymd[0]) != 4
|
||||
or false === checkdate($ymd[1], $ymd[2], $ymd[0])) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The date <em>%s</em> is not valid.'), htmlspecialchars($date)));
|
||||
}
|
||||
return $date;
|
||||
}
|
||||
|
||||
static function manytomany($vals, $form=array(), $p=array())
|
||||
{
|
||||
$res = array();
|
||||
foreach ($vals as $val) {
|
||||
$res[] = Pluf_Encoder::integer($val);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
static function float($val, $form=array(), $p=array())
|
||||
{
|
||||
return (float) $val;
|
||||
}
|
||||
|
||||
/*
|
||||
'file' => "''",
|
||||
'manytomany' => null,
|
||||
'foreignkey' => 0,
|
||||
'text' => "''",
|
||||
'html' => "''",
|
||||
'time' => 0,
|
||||
'integer' => 0,
|
||||
);
|
||||
*/
|
||||
}
|
117
pluf/src/Pluf/Error.php
Normal file
117
pluf/src/Pluf/Error.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume CMS, a website management application.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume CMS is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume CMS 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/**
|
||||
* Error handling class.
|
||||
*
|
||||
* @credits Basis idea from Olivier Meunier
|
||||
*/
|
||||
class Pluf_Error
|
||||
{
|
||||
private $error = array(); /**< Current errors. */
|
||||
|
||||
|
||||
/**
|
||||
* Reset the errors
|
||||
*/
|
||||
function resetError()
|
||||
{
|
||||
$this->error = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an error.
|
||||
*
|
||||
* By convention the number is 4xx if the error is coming from
|
||||
* the user or 5xx if coming from the system (database error for ex.)
|
||||
*
|
||||
* @param string Error message
|
||||
* @param int Error number (0)
|
||||
*/
|
||||
function setError($msg, $no=0)
|
||||
{
|
||||
$this->error[] = array($no,$msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the errors.
|
||||
*
|
||||
* @param bool Errors as HTML list (false)
|
||||
* @param bool Show numbers (true)
|
||||
* @return mixed array of errors, HTML list, or false if no errors
|
||||
*/
|
||||
function error($html=false, $with_nb=true)
|
||||
{
|
||||
if (count($this->error) > 0) {
|
||||
if (!$html) {
|
||||
return $this->error;
|
||||
} else {
|
||||
$res = '<ul>'."\n";
|
||||
foreach($this->error as $v) {
|
||||
$res .= '<li>'.
|
||||
(($with_nb) ?
|
||||
'<span class="errno">'.$v[0].'</span> - ' :
|
||||
'').
|
||||
'<span class="errmsg">'.$v[1].'</span></li>'."\n";
|
||||
}
|
||||
return $res."</ul>\n";
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to set the error from the DB.
|
||||
*
|
||||
* @param string Error message from the DB
|
||||
*/
|
||||
function setDbError($db_error_msg)
|
||||
{
|
||||
$this->setError(__('DB error:').' '.$db_error_msg, 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk set errors.
|
||||
*
|
||||
* Used when you went to recopy the errors of one object into
|
||||
* another. You can call that way:
|
||||
* $object->bulkSetErrors($otherobject->error());
|
||||
*
|
||||
* @param array List of errors
|
||||
* @return bool Success
|
||||
*/
|
||||
function bulkSetError($errors)
|
||||
{
|
||||
if (!is_array($errors)) {
|
||||
return false;
|
||||
}
|
||||
foreach ($errors as $e) {
|
||||
$this->setError($e[1], $e[0]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
26
pluf/src/Pluf/Exception.php
Normal file
26
pluf/src/Pluf/Exception.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Exception extends Exception
|
||||
{
|
||||
}
|
26
pluf/src/Pluf/Exception/DoesNotExist.php
Normal file
26
pluf/src/Pluf/Exception/DoesNotExist.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Exception_DoesNotExist extends Pluf_Exception
|
||||
{
|
||||
}
|
26
pluf/src/Pluf/Exception/NotImplemented.php
Normal file
26
pluf/src/Pluf/Exception/NotImplemented.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Exception_NotImplemented extends Pluf_Exception
|
||||
{
|
||||
}
|
26
pluf/src/Pluf/Exception/SettingError.php
Normal file
26
pluf/src/Pluf/Exception/SettingError.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Exception_SettingError extends Pluf_Exception
|
||||
{
|
||||
}
|
414
pluf/src/Pluf/Form.php
Normal file
414
pluf/src/Pluf/Form.php
Normal file
@@ -0,0 +1,414 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Form validation class.
|
||||
*
|
||||
* This class is used to generate a form. You basically build it the
|
||||
* same way you build a model.
|
||||
*
|
||||
* The form handling is heavily inspired by the Django form handling.
|
||||
*
|
||||
*/
|
||||
class Pluf_Form implements Iterator, ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The fields of the form.
|
||||
*
|
||||
* They are the fully populated Pluf_Form_Field_* of the form. You
|
||||
* define them in the initFields method.
|
||||
*/
|
||||
public $fields = array();
|
||||
|
||||
/**
|
||||
* Prefix for the names of the fields.
|
||||
*/
|
||||
public $prefix = '';
|
||||
public $id_fields = 'id_%s';
|
||||
public $data = array();
|
||||
public $cleaned_data = array();
|
||||
public $errors = array();
|
||||
public $is_bound = false;
|
||||
public $f = null;
|
||||
public $label_suffix = ':';
|
||||
|
||||
protected $is_valid = null;
|
||||
|
||||
function __construct($data=null, $extra=array(), $label_suffix=null)
|
||||
{
|
||||
if ($data !== null) {
|
||||
$this->data = $data;
|
||||
$this->is_bound = true;
|
||||
}
|
||||
if ($label_suffix !== null) $this->label_suffix = $label_suffix;
|
||||
|
||||
$this->initFields($extra);
|
||||
$this->f = new Pluf_Form_FieldProxy($this);
|
||||
}
|
||||
|
||||
function initFields($extra=array())
|
||||
{
|
||||
throw new Exception('Definition of the fields not implemented.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the prefix to the form names.
|
||||
*
|
||||
* @param string Field name.
|
||||
* @return string Field name or field name with form prefix.
|
||||
*/
|
||||
function addPrefix($field_name)
|
||||
{
|
||||
if ('' !== $this->prefix) {
|
||||
return $this->prefix.'-'.$field_name;
|
||||
}
|
||||
return $field_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the form is valid.
|
||||
*
|
||||
* It is also encoding the data in the form to be then saved. It
|
||||
* is very simple as it leaves the work to the field. It means
|
||||
* that you can easily extend this form class to have a more
|
||||
* complex validation procedure like checking if a field is equals
|
||||
* to another in the form (like for password confirmation) etc.
|
||||
*
|
||||
* @param array Associative array of the request
|
||||
* @return array Array of errors
|
||||
*/
|
||||
function isValid()
|
||||
{
|
||||
if ($this->is_valid !== null) {
|
||||
return $this->is_valid;
|
||||
}
|
||||
$this->cleaned_data = array();
|
||||
$this->errors = array();
|
||||
$form_methods = get_class_methods($this);
|
||||
$form_vars = get_object_vars($this);
|
||||
foreach ($this->fields as $name=>$field) {
|
||||
$value = $field->widget->valueFromFormData($this->addPrefix($name),
|
||||
$this->data);
|
||||
try {
|
||||
$value = $field->clean($value);
|
||||
$this->cleaned_data[$name] = $value;
|
||||
$method = 'clean_'.$name;
|
||||
if (in_array($method, $form_methods)) {
|
||||
$value = $this->$method();
|
||||
$this->cleaned_data[$name] = $value;
|
||||
} else if (array_key_exists($method, $form_vars) &&
|
||||
is_callable($this->$method)) {
|
||||
$value = call_user_func($this->$method, $this);
|
||||
$this->cleaned_data[$name] = $value;
|
||||
}
|
||||
} catch (Pluf_Form_Invalid $e) {
|
||||
if (!isset($this->errors[$name])) $this->errors[$name] = array();
|
||||
$this->errors[$name][] = $e->getMessage();
|
||||
if (isset($this->cleaned_data[$name])) {
|
||||
unset($this->cleaned_data[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($this->errors)) {
|
||||
try {
|
||||
$this->cleaned_data = $this->clean();
|
||||
} catch (Pluf_Form_Invalid $e) {
|
||||
if (!isset($this->errors['__all__'])) $this->errors['__all__'] = array();
|
||||
$this->errors['__all__'][] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
if (empty($this->errors)) {
|
||||
$this->is_valid = true;
|
||||
return true;
|
||||
}
|
||||
// as some errors, we do not have cleaned data available.
|
||||
$this->failed();
|
||||
$this->cleaned_data = array();
|
||||
$this->is_valid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form wide cleaning function. That way you can check that if an
|
||||
* input is given, then another one somewhere is also given,
|
||||
* etc. If the cleaning is not ok, your method must throw a
|
||||
* Pluf_Form_Invalid exception.
|
||||
*
|
||||
* @return array Cleaned data.
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
return $this->cleaned_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method just called after the validation if the validation
|
||||
* failed. This can be used to remove uploaded
|
||||
* files. $this->['cleaned_data'] will be available but of course
|
||||
* not fully populated and with possible garbage due to the error.
|
||||
*
|
||||
*/
|
||||
public function failed()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get initial data for a given field.
|
||||
*
|
||||
* @param string Field name.
|
||||
* @return string Initial data or '' of not defined.
|
||||
*/
|
||||
public function initial($name)
|
||||
{
|
||||
if (isset($this->fields[$name])) {
|
||||
return $this->fields[$name]->initial;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top errors.
|
||||
*/
|
||||
public function render_top_errors()
|
||||
{
|
||||
$top_errors = (isset($this->errors['__all__'])) ? $this->errors['__all__'] : array();
|
||||
array_walk($top_errors, 'Pluf_Form_htmlspecialcharsArray');
|
||||
return new Pluf_Template_SafeString(Pluf_Form_renderErrorsAsHTML($top_errors), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top errors.
|
||||
*/
|
||||
public function get_top_errors()
|
||||
{
|
||||
return (isset($this->errors['__all__'])) ? $this->errors['__all__'] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to render the form.
|
||||
*
|
||||
* See render_p() for a usage example.
|
||||
*
|
||||
* @credit Django Project (http://www.djangoproject.com/)
|
||||
* @param string Normal row.
|
||||
* @param string Error row.
|
||||
* @param string Row ender.
|
||||
* @param string Help text HTML.
|
||||
* @param bool Should we display errors on a separate row.
|
||||
* @return string HTML of the form.
|
||||
*/
|
||||
protected function htmlOutput($normal_row, $error_row, $row_ender,
|
||||
$help_text_html, $errors_on_separate_row)
|
||||
{
|
||||
$top_errors = (isset($this->errors['__all__'])) ? $this->errors['__all__'] : array();
|
||||
array_walk($top_errors, 'Pluf_Form_htmlspecialcharsArray');
|
||||
$output = array();
|
||||
$hidden_fields = array();
|
||||
foreach ($this->fields as $name=>$field) {
|
||||
$bf = new Pluf_Form_BoundField($this, $field, $name);
|
||||
$bf_errors = $bf->errors;
|
||||
array_walk($bf_errors, 'Pluf_Form_htmlspecialcharsArray');
|
||||
if ($field->widget->is_hidden) {
|
||||
foreach ($bf_errors as $_e) {
|
||||
$top_errors[] = sprintf(__('(Hidden field %1$s) %2$s'),
|
||||
$name, $_e);
|
||||
}
|
||||
$hidden_fields[] = $bf; // Not rendered
|
||||
} else {
|
||||
if ($errors_on_separate_row and count($bf_errors)) {
|
||||
$output[] = sprintf($error_row, Pluf_Form_renderErrorsAsHTML($bf_errors));
|
||||
}
|
||||
if (strlen($bf->label) > 0) {
|
||||
$label = htmlspecialchars($bf->label, ENT_COMPAT, 'UTF-8');
|
||||
if ($this->label_suffix) {
|
||||
if (!in_array(mb_substr($label, -1, 1),
|
||||
array(':','?','.','!'))) {
|
||||
$label .= $this->label_suffix;
|
||||
}
|
||||
}
|
||||
$label = $bf->labelTag($label);
|
||||
} else {
|
||||
$label = '';
|
||||
}
|
||||
if ($bf->help_text) {
|
||||
// $bf->help_text can contains HTML and is not
|
||||
// escaped.
|
||||
$help_text = sprintf($help_text_html, $bf->help_text);
|
||||
} else {
|
||||
$help_text = '';
|
||||
}
|
||||
$errors = '';
|
||||
if (!$errors_on_separate_row and count($bf_errors)) {
|
||||
$errors = Pluf_Form_renderErrorsAsHTML($bf_errors);
|
||||
}
|
||||
$output[] = sprintf($normal_row, $errors, $label,
|
||||
$bf->render_w(), $help_text);
|
||||
}
|
||||
}
|
||||
if (count($top_errors)) {
|
||||
$errors = sprintf($error_row,
|
||||
Pluf_Form_renderErrorsAsHTML($top_errors));
|
||||
array_unshift($output, $errors);
|
||||
}
|
||||
if (count($hidden_fields)) {
|
||||
$_tmp = '';
|
||||
foreach ($hidden_fields as $hd) {
|
||||
$_tmp .= $hd->render_w();
|
||||
}
|
||||
if (count($output)) {
|
||||
$last_row = array_pop($output);
|
||||
$last_row = substr($last_row, 0, -strlen($row_ender)).$_tmp
|
||||
.$row_ender;
|
||||
$output[] = $last_row;
|
||||
} else {
|
||||
$output[] = $_tmp;
|
||||
}
|
||||
|
||||
}
|
||||
return new Pluf_Template_SafeString(implode("\n", $output), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the form as a list of paragraphs.
|
||||
*/
|
||||
public function render_p()
|
||||
{
|
||||
return $this->htmlOutput('<p>%1$s%2$s %3$s%4$s</p>', '%s', '</p>',
|
||||
' %s', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the form as a list without the <ul></ul>.
|
||||
*/
|
||||
public function render_ul()
|
||||
{
|
||||
return $this->htmlOutput('<li>%1$s%2$s %3$s%4$s</li>', '<li>%s</li>',
|
||||
'</li>', ' %s', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the form as a table without <table></table>.
|
||||
*/
|
||||
public function render_table()
|
||||
{
|
||||
return $this->htmlOutput('<tr><th>%2$s</th><td>%1$s%3$s%4$s</td></tr>',
|
||||
'<tr><td colspan="2">%s</td></tr>',
|
||||
'</td></tr>', '<br /><span class="helptext">%s</span>', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloading of the get method.
|
||||
*
|
||||
* The overloading is to be able to use property call in the
|
||||
* templates.
|
||||
*/
|
||||
function __get($prop)
|
||||
{
|
||||
if (!in_array($prop, array('render_p', 'render_ul', 'render_table', 'render_top_errors', 'get_top_errors'))) {
|
||||
return $this->$prop;
|
||||
}
|
||||
return $this->$prop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a given field by key.
|
||||
*/
|
||||
public function field($key)
|
||||
{
|
||||
return new Pluf_Form_BoundField($this, $this->fields[$key], $key);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator method to iterate over the fields.
|
||||
*
|
||||
* Get the current item.
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
$field = current($this->fields);
|
||||
$name = key($this->fields);
|
||||
return new Pluf_Form_BoundField($this, $field, $name);
|
||||
}
|
||||
|
||||
public function key()
|
||||
{
|
||||
return key($this->fields);
|
||||
}
|
||||
|
||||
public function next()
|
||||
{
|
||||
next($this->fields);
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->fields);
|
||||
}
|
||||
|
||||
public function valid()
|
||||
{
|
||||
// We know that the boolean false will not be stored as a
|
||||
// field, so we can test against false to check if valid or
|
||||
// not.
|
||||
return (false !== current($this->fields));
|
||||
}
|
||||
|
||||
public function offsetUnset($index)
|
||||
{
|
||||
unset($this->fields[$index]);
|
||||
}
|
||||
|
||||
public function offsetSet($index, $value)
|
||||
{
|
||||
$this->fields[$index] = $value;
|
||||
}
|
||||
|
||||
public function offsetGet($index)
|
||||
{
|
||||
if (!isset($this->fields[$index])) {
|
||||
throw new Exception('Undefined index: '.$index);
|
||||
}
|
||||
return $this->fields[$index];
|
||||
}
|
||||
|
||||
public function offsetExists($index)
|
||||
{
|
||||
return (isset($this->fields[$index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Pluf_Form_htmlspecialcharsArray(&$item, $key)
|
||||
{
|
||||
$item = htmlspecialchars($item, ENT_COMPAT, 'UTF-8');
|
||||
}
|
||||
|
||||
function Pluf_Form_renderErrorsAsHTML($errors)
|
||||
{
|
||||
$tmp = array();
|
||||
foreach ($errors as $err) {
|
||||
$tmp[] = '<li>'.$err.'</li>';
|
||||
}
|
||||
return '<ul class="errorlist">'.implode("\n", $tmp).'</ul>';
|
||||
}
|
156
pluf/src/Pluf/Form/BoundField.php
Normal file
156
pluf/src/Pluf/Form/BoundField.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* A class to store field, widget and data.
|
||||
*
|
||||
* Used when rendering a form.
|
||||
*/
|
||||
class Pluf_Form_BoundField
|
||||
{
|
||||
public $form = null;
|
||||
public $field = null;
|
||||
public $name = null;
|
||||
public $html_name = null;
|
||||
public $label = null;
|
||||
public $help_text = null;
|
||||
public $errors = array();
|
||||
|
||||
public function __construct($form, $field, $name)
|
||||
{
|
||||
$this->form = $form;
|
||||
$this->field = $field;
|
||||
$this->name = $name;
|
||||
$this->html_name = $this->form->addPrefix($name);
|
||||
if ($this->field->label == '') {
|
||||
$this->label = mb_ereg_replace('/\_/', '/ /', mb_ucfirst($name));
|
||||
} else {
|
||||
$this->label = $this->field->label;
|
||||
}
|
||||
$this->help_text = ($this->field->help_text) ? $this->field->help_text : '';
|
||||
if (isset($this->form->errors[$name])) {
|
||||
$this->errors = $this->form->errors[$name];
|
||||
}
|
||||
}
|
||||
|
||||
public function render_w($widget=null, $attrs=array())
|
||||
{
|
||||
if ($widget === null) {
|
||||
$widget = $this->field->widget;
|
||||
}
|
||||
$id = $this->autoId();
|
||||
if ($id and !array_key_exists('id', $attrs)
|
||||
and !array_key_exists('id', $widget->attrs)) {
|
||||
$attrs['id'] = $id;
|
||||
}
|
||||
if (!$this->form->is_bound) {
|
||||
$data = $this->form->initial($this->name);
|
||||
} else {
|
||||
$data = $this->field->widget->valueFromFormData($this->html_name, $this->form->data);
|
||||
}
|
||||
return $widget->render($this->html_name, $data, $attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML of the label tag. Wraps the given contents in
|
||||
* a <label>, if the field has an ID attribute. Does not
|
||||
* HTML-escape the contents. If contents aren't given, uses the
|
||||
* field's HTML-escaped label. If attrs are given, they're used as
|
||||
* HTML attributes on the <label> tag.
|
||||
*
|
||||
* @param string Content of the label, will not be escaped (null).
|
||||
* @param array Extra attributes.
|
||||
* @return string HTML of the label.
|
||||
*/
|
||||
public function labelTag($contents=null, $attrs=array())
|
||||
{
|
||||
$contents = ($contents) ? $contents : htmlspecialchars($this->label);
|
||||
$widget = $this->field->widget;
|
||||
$id = (isset($widget->attrs['id'])) ? $widget->attrs['id'] : $this->autoId();
|
||||
$_tmp = array();
|
||||
foreach ($attrs as $attr=>$val) {
|
||||
$_tmp[] = $attr.'="'.$val.'"';
|
||||
}
|
||||
if (count($_tmp)) {
|
||||
$attrs = ' '.implode(' ', $_tmp);
|
||||
} else {
|
||||
$attrs = '';
|
||||
}
|
||||
return new Pluf_Template_SafeString(sprintf('<label for="%s"%s>%s</label>',
|
||||
$widget->idForLabel($id), $attrs, $contents), true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates and returns the ID attribute for this BoundField, if
|
||||
* the associated Form has specified auto_id. Returns an empty
|
||||
* string otherwise.
|
||||
*
|
||||
* @return string Id or empty string if no auto id defined.
|
||||
*/
|
||||
public function autoId()
|
||||
{
|
||||
$id_fields = $this->form->id_fields;
|
||||
if (false !== strpos($id_fields, '%s')) {
|
||||
return sprintf($id_fields, $this->html_name);
|
||||
} elseif ($id_fields) {
|
||||
return $this->html_name;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return HTML to display the errors.
|
||||
*/
|
||||
public function fieldErrors()
|
||||
{
|
||||
Pluf::loadFunction('Pluf_Form_renderErrorsAsHTML');
|
||||
return new Pluf_Template_SafeString(Pluf_Form_renderErrorsAsHTML($this->errors), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloading of the property access.
|
||||
*/
|
||||
public function __get($prop)
|
||||
{
|
||||
if (!in_array($prop, array('labelTag', 'fieldErrors', 'render_w'))) {
|
||||
return $this->$prop;
|
||||
}
|
||||
return $this->$prop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render as string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->render_w();
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ucfirst')) {
|
||||
function mb_ucfirst($str) {
|
||||
return mb_strtoupper(mb_substr($str, 0, 1)).mb_substr($str, 1);
|
||||
}
|
||||
}
|
187
pluf/src/Pluf/Form/Field.php
Normal file
187
pluf/src/Pluf/Form/Field.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Default form field.
|
||||
*
|
||||
* A form field is providing a defined set of methods and properties
|
||||
* to be used in the rendering of the fields in forms, in the
|
||||
* conversion of the data from the user input to a form usable by the
|
||||
* models.
|
||||
*/
|
||||
class Pluf_Form_Field
|
||||
{
|
||||
/**
|
||||
* Store the name of the class.
|
||||
*/
|
||||
public $class = 'Pluf_Form_Field';
|
||||
|
||||
/**
|
||||
* Widget. The way to "present" the field to the user.
|
||||
*/
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
public $label = ''; /**< The label of the field. */
|
||||
public $required = false; /**< Allowed to be blank. */
|
||||
public $help_text = ''; /**< Help text for the field. */
|
||||
public $initial = ''; /**< Default value when empty. */
|
||||
public $choices = null; /**< Predefined choices for the field. */
|
||||
|
||||
/*
|
||||
* Following member variables are more for internal cooking.
|
||||
*/
|
||||
public $hidden_widget = 'Pluf_Form_Widget_HiddenInput';
|
||||
public $value = ''; /**< Current value of the field. */
|
||||
/**
|
||||
* Returning multiple values (select multiple etc.)
|
||||
*/
|
||||
public $multiple = false;
|
||||
protected $empty_values = array('', null, array());
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Example:
|
||||
* $field = new Your_Field(array('required'=>true,
|
||||
* 'widget'=>'Pluf_Form_Widget_TextInput',
|
||||
* 'initial'=>'your name here',
|
||||
* 'label'=>__('Your name'),
|
||||
* 'help_text'=>__('You are?'));
|
||||
*
|
||||
* @param array Params of the field.
|
||||
*/
|
||||
function __construct($params=array())
|
||||
{
|
||||
// We basically take the parameters, for each one we grab the
|
||||
// corresponding member variable and populate the $default
|
||||
// array with. Then we merge with the values given in the
|
||||
// parameters and update the member variables.
|
||||
// This allows to pass extra parameters likes 'min_size'
|
||||
// etc. and update the member variables accordingly. This is
|
||||
// practical when you extend this class with your own class.
|
||||
$default = array();
|
||||
foreach ($params as $key=>$in) {
|
||||
if ($key !== 'widget_attrs')
|
||||
$default[$key] = $this->$key; // Here on purpose it
|
||||
// will fail if a
|
||||
// parameter not needed
|
||||
// for this field is
|
||||
// passed.
|
||||
}
|
||||
$m = array_merge($default, $params);
|
||||
foreach ($params as $key=>$in) {
|
||||
if ($key !== 'widget_attrs')
|
||||
$this->$key = $m[$key];
|
||||
}
|
||||
// Set the widget to be an instance and not the string name.
|
||||
$widget_name = $this->widget;
|
||||
if (isset($params['widget_attrs'])) {
|
||||
$attrs = $params['widget_attrs'];
|
||||
} else {
|
||||
$attrs = array();
|
||||
}
|
||||
$widget = new $widget_name($attrs);
|
||||
$attrs = $this->widgetAttrs($widget);
|
||||
if (count($attrs)) {
|
||||
$widget->attrs = array_merge($widget->attrs, $attrs);
|
||||
}
|
||||
$this->widget = $widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate some possible input for the field.
|
||||
*
|
||||
* @param mixed Value to clean.
|
||||
* @return mixed Cleaned data or throw a Pluf_Form_Invalid exception.
|
||||
*/
|
||||
function clean($value)
|
||||
{
|
||||
if (!$this->multiple and $this->required
|
||||
and in_array($value, $this->empty_values)) {
|
||||
throw new Pluf_Form_Invalid(__('This field is required.'));
|
||||
}
|
||||
if ($this->multiple and $this->required and empty($value)) {
|
||||
throw new Pluf_Form_Invalid(__('This field is required.'));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default empty value for a field.
|
||||
*
|
||||
* @param mixed Value
|
||||
* @return mixed Value
|
||||
*/
|
||||
function setDefaultEmpty($value)
|
||||
{
|
||||
if (in_array($value, $this->empty_values) and !$this->multiple) {
|
||||
$value = '';
|
||||
}
|
||||
if (in_array($value, $this->empty_values) and $this->multiple) {
|
||||
$value = array();
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-clean a value.
|
||||
*
|
||||
* If you are getting multiple values, you need to go through all
|
||||
* of them and validate them against the requirements. This will
|
||||
* do that for you. Basically, it is cloning the field, marking it
|
||||
* as not multiple and validate each value. It will throw an
|
||||
* exception in case of failure.
|
||||
*
|
||||
* If you are implementing your own field which could be filled by
|
||||
* a "multiple" widget, you need to perform a check on
|
||||
* $this->multiple.
|
||||
*
|
||||
* @see Pluf_Form_Field_Integer::clean
|
||||
*
|
||||
* @param array Values
|
||||
* @return array Values
|
||||
*/
|
||||
public function multiClean($value)
|
||||
{
|
||||
$field = clone($this);
|
||||
$field->multiple = false;
|
||||
reset($value);
|
||||
while (list($i, $val) = each($value)) {
|
||||
$value[$i] = $field->clean($val);
|
||||
}
|
||||
reset($value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML attributes to add to the field.
|
||||
*
|
||||
* @param object Widget
|
||||
* @return array HTML attributes.
|
||||
*/
|
||||
public function widgetAttrs($widget)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
36
pluf/src/Pluf/Form/Field/Boolean.php
Normal file
36
pluf/src/Pluf/Form/Field/Boolean.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Boolean extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_CheckboxInput';
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
//parent::clean($value);
|
||||
if (in_array($value, array('on', 'y', '1', 1, true))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
55
pluf/src/Pluf/Form/Field/Date.php
Normal file
55
pluf/src/Pluf/Form/Field/Date.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Date extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
public $input_formats = array(
|
||||
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', // 2006-10-25, 10/25/2006, 10/25/06
|
||||
'%b %d %Y', '%b %d, %Y', // 'Oct 25 2006', 'Oct 25, 2006'
|
||||
'%d %b %Y', '%d %b, %Y', // '25 Oct 2006', '25 Oct, 2006'
|
||||
'%B %d %Y', '%B %d, %Y', // 'October 25 2006', 'October 25, 2006'
|
||||
'%d %B %Y', '%d %B, %Y', // '25 October 2006', '25 October, 2006'
|
||||
);
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (in_array($value, $this->empty_values)) {
|
||||
return '';
|
||||
}
|
||||
foreach ($this->input_formats as $format) {
|
||||
if (false !== ($date = strptime($value, $format))) {
|
||||
$day = $date['tm_mday'];
|
||||
$month = $date['tm_mon'] + 1;
|
||||
$year = $date['tm_year'] + 1900;
|
||||
if (checkdate($month, $day, $year)) {
|
||||
return str_pad($year, 4, '0', STR_PAD_LEFT).'-'.
|
||||
str_pad($month, 2, '0', STR_PAD_LEFT).'-'.
|
||||
str_pad($day, 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Pluf_Form_Invalid(__('Enter a valid date.'));
|
||||
}
|
||||
}
|
68
pluf/src/Pluf/Form/Field/Datetime.php
Normal file
68
pluf/src/Pluf/Form/Field/Datetime.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Datetime extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_DatetimeInput';
|
||||
public $input_formats = array(
|
||||
'%Y-%m-%d %H:%M:%S', // '2006-10-25 14:30:59'
|
||||
'%Y-%m-%d %H:%M', // '2006-10-25 14:30'
|
||||
'%Y-%m-%d', // '2006-10-25'
|
||||
'%m/%d/%Y %H:%M:%S', // '10/25/2006 14:30:59'
|
||||
'%m/%d/%Y %H:%M', // '10/25/2006 14:30'
|
||||
'%m/%d/%Y', // '10/25/2006'
|
||||
'%m/%d/%y %H:%M:%S', // '10/25/06 14:30:59'
|
||||
'%m/%d/%y %H:%M', // '10/25/06 14:30'
|
||||
'%m/%d/%y', // '10/25/06'
|
||||
);
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (in_array($value, $this->empty_values)) {
|
||||
return '';
|
||||
}
|
||||
foreach ($this->input_formats as $format) {
|
||||
if (false !== ($date = strptime($value, $format))) {
|
||||
$day = $date['tm_mday'];
|
||||
$month = $date['tm_mon'] + 1;
|
||||
$year = $date['tm_year'] + 1900;
|
||||
// PHP's strptime has various quirks, e.g. it doesn't check
|
||||
// gregorian dates for validity and it also allows '60' in
|
||||
// the seconds part
|
||||
if (checkdate($month, $day, $year) && $date['tm_sec'] < 60) {
|
||||
$date = str_pad($year, 4, '0', STR_PAD_LEFT).'-'.
|
||||
str_pad($month, 2, '0', STR_PAD_LEFT).'-'.
|
||||
str_pad($day, 2, '0', STR_PAD_LEFT).' '.
|
||||
str_pad($date['tm_hour'], 2, '0', STR_PAD_LEFT).':'.
|
||||
str_pad($date['tm_min'], 2, '0', STR_PAD_LEFT).':';
|
||||
str_pad($date['tm_sec'], 2, '0', STD_PAD_LEFT);
|
||||
|
||||
// we internally use GMT, so we convert it to a GMT date.
|
||||
return gmdate('Y-m-d H:i:s', strtotime($date));
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Pluf_Form_Invalid(__('Enter a valid date/time.'));
|
||||
}
|
||||
}
|
42
pluf/src/Pluf/Form/Field/Email.php
Normal file
42
pluf/src/Pluf/Form/Field/Email.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Email extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (in_array($value, $this->empty_values)) {
|
||||
$value = '';
|
||||
}
|
||||
if ($value == '') {
|
||||
return $value;
|
||||
}
|
||||
if (!Pluf_Utils::isValidEmail($value)) {
|
||||
throw new Pluf_Form_Invalid(__('Enter a valid email address.'));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
151
pluf/src/Pluf/Form/Field/File.php
Normal file
151
pluf/src/Pluf/Form/Field/File.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_File extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_FileInput';
|
||||
public $move_function = 'Pluf_Form_Field_File_moveToUploadFolder';
|
||||
public $max_size = 2097152; // 2MB
|
||||
public $move_function_params = array();
|
||||
|
||||
/**
|
||||
* Validate some possible input for the field.
|
||||
*
|
||||
* @param mixed Input
|
||||
* @return string Path to the file relative to 'upload_path'
|
||||
*/
|
||||
function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (is_null($value) and !$this->required) {
|
||||
return ''; // no file
|
||||
} elseif (is_null($value) and $this->required) {
|
||||
throw new Pluf_Form_Invalid(__('No files were uploaded. Please try to send the file again.'));
|
||||
}
|
||||
$errors = array();
|
||||
$no_files = false;
|
||||
switch ($value['error']) {
|
||||
case UPLOAD_ERR_OK:
|
||||
break;
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The uploaded file is too large. Reduce the size of the file to %s and send it again.'),
|
||||
Pluf_Utils::prettySize(ini_get('upload_max_filesize'))));
|
||||
break;
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The uploaded file is too large. Reduce the size of the file to %s and send it again.'),
|
||||
Pluf_Utils::prettySize($_REQUEST['MAX_FILE_SIZE'])));
|
||||
break;
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
throw new Pluf_Form_Invalid(__('The upload did not complete. Please try to send the file again.'));
|
||||
break;
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
if ($this->required) {
|
||||
throw new Pluf_Form_Invalid(__('No files were uploaded. Please try to send the file again.'));
|
||||
} else {
|
||||
return ''; // no file
|
||||
}
|
||||
break;
|
||||
case UPLOAD_ERR_NO_TMP_DIR:
|
||||
case UPLOAD_ERR_CANT_WRITE:
|
||||
throw new Pluf_Form_Invalid(__('The server has no temporary folder correctly configured to store the uploaded file.'));
|
||||
break;
|
||||
case UPLOAD_ERR_EXTENSION:
|
||||
throw new Pluf_Form_Invalid(__('The uploaded file has been stopped by an extension.'));
|
||||
break;
|
||||
default:
|
||||
throw new Pluf_Form_Invalid(__('An error occured when upload the file. Please try to send the file again.'));
|
||||
}
|
||||
if ($value['size'] > $this->max_size) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('The uploaded file is to big (%1$s). Reduce the size to less than %2$s and try again.'),
|
||||
Pluf_Utils::prettySize($value['size']),
|
||||
Pluf_Utils::prettySize($this->max_size)));
|
||||
}
|
||||
// copy the file to the final destination and updated $value
|
||||
// with the final path name. 'final_name' is relative to
|
||||
// Pluf::f('upload_path')
|
||||
Pluf::loadFunction($this->move_function);
|
||||
// Should throw a Pluf_Form_Invalid exception if error or the
|
||||
// value to be stored in the database.
|
||||
return call_user_func($this->move_function, $value,
|
||||
$this->move_function_params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default move function. The file name is sanitized.
|
||||
*
|
||||
* In the extra parameters, options can be used so that this function is
|
||||
* matching most of the needs:
|
||||
*
|
||||
* * 'upload_path': The path in which the uploaded file will be
|
||||
* stored.
|
||||
* * 'upload_path_create': If set to true, try to create the
|
||||
* upload path if not existing.
|
||||
*
|
||||
* * 'upload_overwrite': Set it to true if you want to allow overwritting.
|
||||
*
|
||||
* * 'file_name': Force the file name to this name and do not use the
|
||||
* original file name. If this name contains '%s' for
|
||||
* example 'myid-%s', '%s' will be replaced by the
|
||||
* original filename. This can be used when for
|
||||
* example, you want to prefix with the id of an
|
||||
* article all the files attached to this article.
|
||||
*
|
||||
* If you combine those options, you can dynamically generate the path
|
||||
* name in your form (for example date base) and let this upload
|
||||
* function create it on demand.
|
||||
*
|
||||
* @param array Upload value of the form.
|
||||
* @param array Extra parameters. If upload_path key is set, use it. (array())
|
||||
* @return string Name relative to the upload path.
|
||||
*/
|
||||
function Pluf_Form_Field_File_moveToUploadFolder($value, $params=array())
|
||||
{
|
||||
$name = Pluf_Utils::cleanFileName($value['name']);
|
||||
$upload_path = Pluf::f('upload_path', '/tmp');
|
||||
if (isset($params['file_name'])) {
|
||||
if (false !== strpos($params['file_name'], '%s')) {
|
||||
$name = sprintf($params['file_name'], $name);
|
||||
} else {
|
||||
$name = $params['file_name'];
|
||||
}
|
||||
}
|
||||
if (isset($params['upload_path'])) {
|
||||
$upload_path = $params['upload_path'];
|
||||
}
|
||||
$dest = $upload_path.'/'.$name;
|
||||
if (isset($params['upload_path_create'])
|
||||
and !is_dir(dirname($dest))) {
|
||||
if (false == @mkdir(dirname($dest), 0777, true)) {
|
||||
throw new Pluf_Form_Invalid(__('An error occured when creating the upload path. Please try to send the file again.'));
|
||||
}
|
||||
}
|
||||
if ((!isset($params['upload_overwrite']) or $params['upload_overwrite'] == false) and file_exists($dest)) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('A file with the name "%s" has already been uploaded.'), $name));
|
||||
}
|
||||
if (@!move_uploaded_file($value['tmp_name'], $dest)) {
|
||||
throw new Pluf_Form_Invalid(__('An error occured when uploading the file. Please try to send the file again.'));
|
||||
}
|
||||
@chmod($dest, 0666);
|
||||
return $name;
|
||||
}
|
48
pluf/src/Pluf/Form/Field/Float.php
Normal file
48
pluf/src/Pluf/Form/Field/Float.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Float extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
public $max_value = null;
|
||||
public $min_value = null;
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (in_array($value, $this->empty_values)) {
|
||||
$value = '';
|
||||
}
|
||||
if (!is_numeric($value)) {
|
||||
throw new Pluf_Form_Invalid(__('Enter a number.'));
|
||||
}
|
||||
$value = (float) $value;
|
||||
if ($this->max_value !== null and $this->max_value < $value) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('Ensure this value is less than or equal to %s.'), $this->max_value));
|
||||
}
|
||||
if ($this->min_value !== null and $this->min_value > $value) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('Ensure this value is greater than or equal to %s.'), $this->min_value));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
56
pluf/src/Pluf/Form/Field/Integer.php
Normal file
56
pluf/src/Pluf/Form/Field/Integer.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Integer extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
public $max = null;
|
||||
public $min = null;
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
$value = $this->setDefaultEmpty($value);
|
||||
if ($this->multiple) {
|
||||
return $this->multiClean($value);
|
||||
} else {
|
||||
if ($value == '') return $value;
|
||||
if (!preg_match('/^[\+\-]?[0-9]+$/', $value)) {
|
||||
throw new Pluf_Form_Invalid(__('The value must be an integer.'));
|
||||
}
|
||||
$this->checkMinMax($value);
|
||||
}
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
protected function checkMinMax($value)
|
||||
{
|
||||
if ($this->max !== null and $value > $this->max) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('Ensure that this value is not greater than %1$d.'), $this->max));
|
||||
}
|
||||
if ($this->min !== null and $value < $this->min) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('Ensure that this value is not lower than %1$d.'), $this->min));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
170
pluf/src/Pluf/Form/Field/ReCaptcha.php
Normal file
170
pluf/src/Pluf/Form/Field/ReCaptcha.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Add ReCaptcha control to your forms.
|
||||
*
|
||||
* You need first to get a ReCaptcha account, create a domain and get
|
||||
* the API keys for your domain. Check http://recaptcha.net/ for more
|
||||
* information.
|
||||
*
|
||||
* The recaptcha field needs to know the IP address of the user
|
||||
* submitting the form and if the request is made over SSL or
|
||||
* not. This means that you need to provide the $request object in the
|
||||
* extra parameters of your form.
|
||||
*
|
||||
* To add the ReCaptcha field to your form, simply add the following
|
||||
* to your form object (note the use of $extra['request']):
|
||||
*
|
||||
* <pre>
|
||||
* $ssl = (!empty($extra['request']->SERVER['HTTPS'])
|
||||
* and $extra['request']->SERVER['HTTPS'] != 'off');
|
||||
*
|
||||
* $this->fields['recaptcha'] = new Pluf_Form_Field_ReCaptcha(
|
||||
* array('required' => true,
|
||||
* 'label' => __('Please solve this challenge'),
|
||||
* 'privkey' => 'PRIVATE_RECAPTCHA_KEY_HERE',
|
||||
* 'remoteip' => $extra['request']->remote_addr,
|
||||
* 'widget_attrs' => array(
|
||||
* 'pubkey' => 'PUBLIC_RECAPTCHA_KEY_HERE',
|
||||
* ),
|
||||
* ));
|
||||
* </pre>
|
||||
*
|
||||
* Then in your template, you simply need to add the ReCaptcha field:
|
||||
*
|
||||
* <pre>
|
||||
* {if $form.f.recaptcha.errors}{$form.f.recaptcha.fieldErrors}{/if}
|
||||
* {$form.f.recaptcha|safe}
|
||||
* </pre>
|
||||
*
|
||||
* Based on http://recaptcha.googlecode.com/files/recaptcha-php-1.10.zip
|
||||
*
|
||||
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
||||
* AUTHORS:
|
||||
* Mike Crawford
|
||||
* Ben Maurer
|
||||
*/
|
||||
class Pluf_Form_Field_ReCaptcha extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_ReCaptcha';
|
||||
public $privkey = '';
|
||||
public $remoteip = '';
|
||||
public $extra_params = array();
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
// will throw the Pluf_Form_Invalid exception in case of
|
||||
// error.
|
||||
self::checkAnswer($this->privkey, $this->remoteip,
|
||||
$value[0], $value[1], $this->extra_params);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits an HTTP POST to a reCAPTCHA server
|
||||
*
|
||||
* @param string Host
|
||||
* @param string Path
|
||||
* @param array Data
|
||||
* @param int port (80
|
||||
* @return array response
|
||||
*/
|
||||
public static function httpPost($host, $path, $data, $port=80)
|
||||
{
|
||||
|
||||
$req = self::qsencode($data);
|
||||
$http_request = "POST $path HTTP/1.0\r\n";
|
||||
$http_request .= "Host: $host\r\n";
|
||||
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
|
||||
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
|
||||
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
|
||||
$http_request .= "\r\n";
|
||||
$http_request .= $req;
|
||||
|
||||
if (false === ($fs=@fsockopen($host, $port, $errno, $errstr, 10))) {
|
||||
throw new Pluf_Form_Invalid(__('Cannot connect to the reCaptcha server for validation.'));
|
||||
}
|
||||
fwrite($fs, $http_request);
|
||||
$response = '';
|
||||
while (!feof($fs)) {
|
||||
$response .= fgets($fs, 1160); // One TCP-IP packet
|
||||
}
|
||||
fclose($fs);
|
||||
return explode("\r\n\r\n", $response, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given data into a query string format
|
||||
*
|
||||
* @param array Array of string elements to be encoded
|
||||
* @return string Encoded request
|
||||
*/
|
||||
public static function qsencode($data)
|
||||
{
|
||||
$d = array();
|
||||
foreach ($data as $key => $value) {
|
||||
$d[] = $key.'='.urlencode(stripslashes($value));
|
||||
}
|
||||
return implode('&', $d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls an HTTP POST function to verify if the user's guess was correct
|
||||
* @param string $privkey
|
||||
* @param string $remoteip
|
||||
* @param string $challenge
|
||||
* @param string $response
|
||||
* @param array $extra_params an array of extra variables to post to the server
|
||||
* @return ReCaptchaResponse
|
||||
*/
|
||||
public static function checkAnswer($privkey, $remoteip, $challenge, $response, $extra_params=array())
|
||||
{
|
||||
if ($privkey == '') {
|
||||
throw new Pluf_Form_Invalid(__('To use reCAPTCHA you must set your API key.'));
|
||||
}
|
||||
if ($remoteip == '') {
|
||||
throw new Pluf_Form_Invalid(__('For security reasons, you must pass the remote ip to reCAPTCHA.'));
|
||||
}
|
||||
//discard spam submissions
|
||||
if (strlen($challenge) == 0 || strlen($response) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response = self::httpPost('api-verify.recaptcha.net', '/verify',
|
||||
array(
|
||||
'privatekey' => $privkey,
|
||||
'remoteip' => $remoteip,
|
||||
'challenge' => $challenge,
|
||||
'response' => $response
|
||||
) + $extra_params
|
||||
);
|
||||
|
||||
$answers = explode("\n", $response[1]);
|
||||
if (trim($answers[0]) == 'true') {
|
||||
return true;
|
||||
} else {
|
||||
throw new Pluf_Form_Invalid($answers[1]);
|
||||
}
|
||||
}
|
||||
}
|
111
pluf/src/Pluf/Form/Field/Slug.php
Normal file
111
pluf/src/Pluf/Form/Field/Slug.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2010 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Slug extends Pluf_Form_Field
|
||||
{
|
||||
/**
|
||||
* Name of the widget to use for build the forms.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
|
||||
/**
|
||||
* Minimum size of field.
|
||||
*
|
||||
* Default to 1.
|
||||
*
|
||||
* @var int
|
||||
**/
|
||||
public $min_size = 1;
|
||||
|
||||
/**
|
||||
* Maximum size of field.
|
||||
*
|
||||
* Default to 50.
|
||||
*
|
||||
* @var int
|
||||
**/
|
||||
public $max_size = 50;
|
||||
|
||||
protected $_error_messages = array();
|
||||
|
||||
public function __construct($params=array())
|
||||
{
|
||||
if (in_array($this->help_text, $this->empty_values)) {
|
||||
$this->help_text = __('The “slug” is the URL-friendly'.
|
||||
' version of the name, consisting of '.
|
||||
'letters, numbers, underscores or hyphens.');
|
||||
}
|
||||
$this->_error_messages = array(
|
||||
'min_size' => __('Ensure this value has at most %1$d characters (it has %2$d).'),
|
||||
'max_size' => __('Ensure this value has at least %1$d characters (it has %2$d).')
|
||||
);
|
||||
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any character not allowed and valid the size of the field.
|
||||
*
|
||||
* @see Pluf_Form_Field::clean()
|
||||
* @throws Pluf_Form_Invalid If the lenght of the field has not a valid size.
|
||||
*/
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if ($value) {
|
||||
$value = Pluf_DB_Field_Slug::slugify($value);
|
||||
$len = mb_strlen($value, Pluf::f('encoding', 'UTF-8'));
|
||||
if ($this->max_size < $len) {
|
||||
throw new Pluf_Form_Invalid(sprintf($this->_error_messages['max_size'],
|
||||
$this->max_size,
|
||||
$len));
|
||||
}
|
||||
if ($this->min_size > $len) {
|
||||
throw new Pluf_Form_Invalid(sprintf($this->_error_messages['min_size'],
|
||||
$this->min_size,
|
||||
$len));
|
||||
}
|
||||
}
|
||||
else
|
||||
$value = '';
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Pluf_Form_Field::widgetAttrs()
|
||||
*/
|
||||
public function widgetAttrs($widget)
|
||||
{
|
||||
$attrs = array();
|
||||
if (!isset($widget->attrs['maxlength'])) {
|
||||
$attrs['maxlength'] = $this->max_size;
|
||||
} else {
|
||||
$this->max_size = $widget->attrs['maxlength'];
|
||||
}
|
||||
|
||||
return $attrs;
|
||||
}
|
||||
}
|
39
pluf/src/Pluf/Form/Field/Url.php
Normal file
39
pluf/src/Pluf/Form/Field/Url.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Url extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (in_array($value, $this->empty_values)) {
|
||||
return '';
|
||||
}
|
||||
if (!Pluf_Utils::isValidUrl($value)) {
|
||||
throw new Pluf_Form_Invalid(__('Enter a valid address.'));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
57
pluf/src/Pluf/Form/Field/Varchar.php
Normal file
57
pluf/src/Pluf/Form/Field/Varchar.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Field_Varchar extends Pluf_Form_Field
|
||||
{
|
||||
public $widget = 'Pluf_Form_Widget_TextInput';
|
||||
public $max_length = null;
|
||||
public $min_length = null;
|
||||
|
||||
public function clean($value)
|
||||
{
|
||||
parent::clean($value);
|
||||
if (in_array($value, $this->empty_values)) {
|
||||
$value = '';
|
||||
}
|
||||
$value_length = mb_strlen($value);
|
||||
if ($this->max_length !== null and $value_length > $this->max_length) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('Ensure this value has at most %1$d characters (it has %2$d).'), $this->max_length, $value_length));
|
||||
}
|
||||
if ($this->min_length !== null and $value_length < $this->min_length) {
|
||||
throw new Pluf_Form_Invalid(sprintf(__('Ensure this value has at least %1$d characters (it has %2$d).'), $this->min_length, $value_length));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function widgetAttrs($widget)
|
||||
{
|
||||
if ($this->max_length !== null and
|
||||
in_array(get_class($widget),
|
||||
array('Pluf_Form_Widget_TextInput',
|
||||
'Pluf_Form_Widget_PasswordInput'))) {
|
||||
return array('maxlength'=>$this->max_length);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
48
pluf/src/Pluf/Form/FieldProxy.php
Normal file
48
pluf/src/Pluf/Form/FieldProxy.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Field proxy to access a form field through {$form.f.fieldname} in a
|
||||
* template.
|
||||
*/
|
||||
|
||||
class Pluf_Form_FieldProxy
|
||||
{
|
||||
protected $form = null;
|
||||
|
||||
public function __construct(&$form)
|
||||
{
|
||||
$this->form = $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* No control are performed. If you access a non existing field it
|
||||
* will simply throw an error.
|
||||
*/
|
||||
public function __get($field)
|
||||
{
|
||||
return new Pluf_Form_BoundField($this->form,
|
||||
$this->form->fields[$field],
|
||||
$field);
|
||||
}
|
||||
}
|
26
pluf/src/Pluf/Form/Invalid.php
Normal file
26
pluf/src/Pluf/Form/Invalid.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Form_Invalid extends Exception
|
||||
{
|
||||
}
|
87
pluf/src/Pluf/Form/Model.php
Normal file
87
pluf/src/Pluf/Form/Model.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Dynamic form validation class.
|
||||
*
|
||||
* This class is used to generate a form for a given model.
|
||||
*/
|
||||
class Pluf_Form_Model extends Pluf_Form
|
||||
{
|
||||
/**
|
||||
* The model for which the form applies.
|
||||
*/
|
||||
public $model = null;
|
||||
|
||||
function initFields($extra=array())
|
||||
{
|
||||
$this->model = $extra['model'];
|
||||
if (isset($extra['fields'])) {
|
||||
// Only display a subset of the fields
|
||||
$cols = array();
|
||||
foreach ($extra['fields'] as $field) {
|
||||
$cols[$field] = $this->model->_a['cols'][$field];
|
||||
}
|
||||
} else {
|
||||
$cols = $this->model->_a['cols'];
|
||||
}
|
||||
foreach ($cols as $name=>$def) {
|
||||
$db_field = new $def['type']('', $name);
|
||||
$def = array_merge(array('blank' => true,
|
||||
'verbose' => $name,
|
||||
'help_text' => '',
|
||||
'editable' => true),
|
||||
$def);
|
||||
if ($def['editable']) {
|
||||
// The 'model_instance' and 'name' are used by the
|
||||
// ManyToMany field.
|
||||
$def['model_instance'] = $this->model;
|
||||
$def['name'] = $name;
|
||||
if (null !== ($form_field=$db_field->formField($def))) {
|
||||
$this->fields[$name] = $form_field;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model in the database.
|
||||
*
|
||||
* @param bool Commit in the database or not. If not, the object
|
||||
* is returned but not saved in the database.
|
||||
* @return Object Model with data set from the form.
|
||||
*/
|
||||
function save($commit=true)
|
||||
{
|
||||
if ($this->isValid()) {
|
||||
$this->model->setFromFormData($this->cleaned_data);
|
||||
if ($commit && $this->model->id) {
|
||||
$this->model->update();
|
||||
} elseif ($commit) {
|
||||
$this->model->create();
|
||||
}
|
||||
return $this->model;
|
||||
}
|
||||
throw new Exception(__('Cannot save the model from an invalid form.'));
|
||||
}
|
||||
}
|
116
pluf/src/Pluf/Form/Widget.php
Normal file
116
pluf/src/Pluf/Form/Widget.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Base class to display a form field.
|
||||
*
|
||||
*/
|
||||
class Pluf_Form_Widget
|
||||
{
|
||||
public $is_hidden = false; /**< Is an hidden field? */
|
||||
public $needs_multipart_form = false; /**< Do we need multipart? */
|
||||
public $input_type = ''; /**< Input type of the field. */
|
||||
public $attrs = array(); /**< HTML attributes for the widget. */
|
||||
|
||||
public function __construct($attrs=array())
|
||||
{
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
throw new Exception('Not Implemented.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the list of attributes for the form.
|
||||
* It should be called this way:
|
||||
* $this->buildAttrs(array('name'=>$name, 'type'=>$this->input_type),
|
||||
* $extra_attrs);
|
||||
*
|
||||
* @param array Contains the name and type attributes.
|
||||
* @param array Extra attributes, like 'class' for example.
|
||||
* @return array The attributes for the field.
|
||||
*/
|
||||
protected function buildAttrs($attrs, $extra_attrs=array())
|
||||
{
|
||||
return array_merge($this->attrs, $attrs, $extra_attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* A widget can split itself in multiple input form. For example
|
||||
* you can have a datetime value in your model and you use 2
|
||||
* inputs one for the date and one for the time to input the
|
||||
* value. So the widget must know how to get back the values from
|
||||
* the submitted form.
|
||||
*
|
||||
* @param string Name of the form.
|
||||
* @param array Submitted form data.
|
||||
* @return mixed Value or null if not defined.
|
||||
*/
|
||||
public function valueFromFormData($name, $data)
|
||||
{
|
||||
if (isset($data[$name])) {
|
||||
return $data[$name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML ID attribute of this Widget for use by a
|
||||
* <label>, given the ID of the field. Returns None if no ID is
|
||||
* available.
|
||||
*
|
||||
* This hook is necessary because some widgets have multiple HTML
|
||||
* elements and, thus, multiple IDs. In that case, this method
|
||||
* should return an ID value that corresponds to the first ID in
|
||||
* the widget's tags.
|
||||
*/
|
||||
public function idForLabel($id)
|
||||
{
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array in a string ready to use for HTML attributes.
|
||||
*
|
||||
* As all the widget will extend the Pluf_Form_Widget class, it means
|
||||
* that this function is available directly in the extended class.
|
||||
*/
|
||||
function Pluf_Form_Widget_Attrs($attrs)
|
||||
{
|
||||
$_tmp = array();
|
||||
foreach ($attrs as $attr=>$val) {
|
||||
$_tmp[] = $attr.'="'.$val.'"';
|
||||
}
|
||||
return ' '.implode(' ', $_tmp);
|
||||
}
|
66
pluf/src/Pluf/Form/Widget/CheckboxInput.php
Normal file
66
pluf/src/Pluf/Form/Widget/CheckboxInput.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple checkbox.
|
||||
*/
|
||||
class Pluf_Form_Widget_CheckboxInput extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'checkbox';
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
if ((bool)$value) {
|
||||
// We consider that if a value can be boolean casted to
|
||||
// true, then we check the box.
|
||||
$extra_attrs['checked'] = 'checked';
|
||||
}
|
||||
// Value of a checkbox is always "1" but when not checked, the
|
||||
// corresponding key in the form associative array is not set.
|
||||
return parent::render($name, '1', $extra_attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* A non checked checkbox is simply not returned in the form array.
|
||||
*
|
||||
* @param string Name of the form.
|
||||
* @param array Submitted form data.
|
||||
* @return mixed Value or null if not defined.
|
||||
*/
|
||||
public function valueFromFormData($name, $data)
|
||||
{
|
||||
if (!isset($data[$name]) or false === $data[$name]
|
||||
or (string)$data[$name] === '0' or $data[$name] == '') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
50
pluf/src/Pluf/Form/Widget/DatetimeInput.php
Normal file
50
pluf/src/Pluf/Form/Widget/DatetimeInput.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple input of type datetime.
|
||||
*/
|
||||
class Pluf_Form_Widget_DatetimeInput extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'text';
|
||||
public $format = 'Y-m-d H:i'; // '2006-10-25 14:30' by default do
|
||||
// not show the seconds.
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
// Internally we use GMT, so we convert back to the current
|
||||
// timezone.
|
||||
if (strlen($value) > 0) {
|
||||
$value = date($this->format, strtotime($value.' GMT'));
|
||||
}
|
||||
return parent::render($name, $value, $extra_attrs);
|
||||
}
|
||||
}
|
38
pluf/src/Pluf/Form/Widget/FileInput.php
Normal file
38
pluf/src/Pluf/Form/Widget/FileInput.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple input of type file.
|
||||
*/
|
||||
class Pluf_Form_Widget_FileInput extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'file';
|
||||
public $needs_multipart_form = true;
|
||||
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
$value = '';
|
||||
return parent::render($name, $value, $extra_attrs);
|
||||
}
|
||||
|
||||
}
|
31
pluf/src/Pluf/Form/Widget/HiddenInput.php
Normal file
31
pluf/src/Pluf/Form/Widget/HiddenInput.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple input of type text.
|
||||
*/
|
||||
class Pluf_Form_Widget_HiddenInput extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'hidden';
|
||||
public $is_hidden = true;
|
||||
}
|
49
pluf/src/Pluf/Form/Widget/Input.php
Normal file
49
pluf/src/Pluf/Form/Widget/Input.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Base class for all the input widgets. (Except radio and checkbox).
|
||||
*/
|
||||
class Pluf_Form_Widget_Input extends Pluf_Form_Widget
|
||||
{
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
if ($value === null) $value = '';
|
||||
$final_attrs = $this->buildAttrs(array('name' => $name,
|
||||
'type' => $this->input_type),
|
||||
$extra_attrs);
|
||||
if ($value !== '') {
|
||||
$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
|
||||
$final_attrs['value'] = $value;
|
||||
}
|
||||
return new Pluf_Template_SafeString('<input'.Pluf_Form_Widget_Attrs($final_attrs).' />', true);
|
||||
}
|
||||
}
|
46
pluf/src/Pluf/Form/Widget/PasswordInput.php
Normal file
46
pluf/src/Pluf/Form/Widget/PasswordInput.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple input of type text.
|
||||
*/
|
||||
class Pluf_Form_Widget_PasswordInput extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'password';
|
||||
public $render_value = true;
|
||||
|
||||
public function __construct($attrs=array())
|
||||
{
|
||||
$this->render_value = (isset($attrs['render_value'])) ? $attrs['render_value'] : $this->render_value;
|
||||
unset($attrs['render_value']);
|
||||
parent::__construct($attrs);
|
||||
}
|
||||
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
if ($this->render_value === false) {
|
||||
$value = '';
|
||||
}
|
||||
return parent::render($name, $value, $extra_attrs);
|
||||
}
|
||||
}
|
106
pluf/src/Pluf/Form/Widget/ReCaptcha.php
Normal file
106
pluf/src/Pluf/Form/Widget/ReCaptcha.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* reCAPTCHA input for your forms.
|
||||
*
|
||||
* Based on http://recaptcha.googlecode.com/files/recaptcha-php-1.10.zip
|
||||
*
|
||||
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
||||
* AUTHORS:
|
||||
* Mike Crawford
|
||||
* Ben Maurer
|
||||
*
|
||||
* @see Pluf_Form_Field_ReCaptcha
|
||||
*
|
||||
*/
|
||||
class Pluf_Form_Widget_ReCaptcha extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'text';
|
||||
public $ssl = false;
|
||||
public $pubkey = '';
|
||||
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
return Pluf_Template::markSafe(self::getHtml($this->attrs['pubkey']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the challenge HTML (javascript and non-javascript
|
||||
* version). This is called from the browser, and the resulting
|
||||
* reCAPTCHA HTML widget is embedded within the HTML form it was
|
||||
* called from.
|
||||
*
|
||||
* @param string A public key for reCAPTCHA
|
||||
* @param string The error given by reCAPTCHA (null)
|
||||
* @param boolean Should the request be made over ssl? (false)
|
||||
* @return string The HTML to be embedded in the user's form.
|
||||
*/
|
||||
public static function getHtml($pubkey, $error=null, $use_ssl=false)
|
||||
{
|
||||
$server = ($use_ssl) ? 'https://api-secure.recaptcha.net'
|
||||
: 'http://api.recaptcha.net';
|
||||
$errorpart = ($error) ? '&error='.$error : '';
|
||||
|
||||
return '<script type="text/javascript" src="'.$server.'/challenge?k='
|
||||
.$pubkey.$errorpart.'"></script>
|
||||
<noscript>
|
||||
<iframe src="'.$server.'/noscript?k='.$pubkey.$errorpart
|
||||
.'" height="300" width="500" frameborder="0"></iframe><br/>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
|
||||
</noscript>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form data from the reCaptcha fields.
|
||||
*
|
||||
* We need to get back two fields from the POST request
|
||||
* 'recaptcha_challenge_field' and 'recaptcha_response_field'.
|
||||
*
|
||||
* They are hardcoded, so we do not even bother checking something
|
||||
* else.
|
||||
*
|
||||
* @param string Name of the form
|
||||
* @param array Submitted form data
|
||||
* @return array Challenge and answer
|
||||
*/
|
||||
public function valueFromFormData($name, $data)
|
||||
{
|
||||
$res = array('', '');
|
||||
$res[0] = isset($data['recaptcha_challenge_field'])
|
||||
? $data['recaptcha_challenge_field'] : '';
|
||||
$res[1] = isset($data['recaptcha_response_field'])
|
||||
? $data['recaptcha_response_field'] : '';
|
||||
return $res;
|
||||
}
|
||||
}
|
78
pluf/src/Pluf/Form/Widget/SelectInput.php
Normal file
78
pluf/src/Pluf/Form/Widget/SelectInput.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple checkbox with grouping.
|
||||
*/
|
||||
class Pluf_Form_Widget_SelectInput extends Pluf_Form_Widget
|
||||
{
|
||||
public $choices = array();
|
||||
|
||||
public function __construct($attrs=array())
|
||||
{
|
||||
$this->choices = $attrs['choices'];
|
||||
unset($attrs['choices']);
|
||||
parent::__construct($attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @param array Extra choices (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array(),
|
||||
$choices=array())
|
||||
{
|
||||
$output = array();
|
||||
if ($value === null) {
|
||||
$value = '';
|
||||
}
|
||||
$final_attrs = $this->buildAttrs(array('name' => $name), $extra_attrs);
|
||||
$output[] = '<select'.Pluf_Form_Widget_Attrs($final_attrs).'>';
|
||||
$groups = $this->choices + $choices;
|
||||
foreach($groups as $option_group => $c) {
|
||||
if (!is_array($c)) {
|
||||
$subchoices = array($option_group => $c);
|
||||
} else {
|
||||
$output[] = '<optgroup label="'.htmlspecialchars($option_group, ENT_COMPAT, 'UTF-8').'">';
|
||||
$subchoices = $c;
|
||||
}
|
||||
foreach ($subchoices as $option_label=>$option_value) {
|
||||
$selected = ($option_value == $value) ? ' selected="selected"':'';
|
||||
$output[] = sprintf('<option value="%s"%s>%s</option>',
|
||||
htmlspecialchars($option_value, ENT_COMPAT, 'UTF-8'),
|
||||
$selected,
|
||||
htmlspecialchars($option_label, ENT_COMPAT, 'UTF-8'));
|
||||
}
|
||||
if (is_array($c)) {
|
||||
$output[] = '</optgroup>';
|
||||
}
|
||||
}
|
||||
$output[] = '</select>';
|
||||
return new Pluf_Template_SafeString(implode("\n", $output), true);
|
||||
}
|
||||
}
|
79
pluf/src/Pluf/Form/Widget/SelectMultipleInput.php
Normal file
79
pluf/src/Pluf/Form/Widget/SelectMultipleInput.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple checkbox.
|
||||
*/
|
||||
class Pluf_Form_Widget_SelectMultipleInput extends Pluf_Form_Widget
|
||||
{
|
||||
public $choices = array();
|
||||
|
||||
public function __construct($attrs=array())
|
||||
{
|
||||
$this->choices = $attrs['choices'];
|
||||
unset($attrs['choices']);
|
||||
parent::__construct($attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param array Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @param array Extra choices (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array(),
|
||||
$choices=array())
|
||||
{
|
||||
$output = array();
|
||||
if ($value === null) {
|
||||
$value = array();
|
||||
}
|
||||
$final_attrs = $this->buildAttrs(array('name' => $name.'[]'),
|
||||
$extra_attrs);
|
||||
$output[] = '<select multiple="multiple"'
|
||||
.Pluf_Form_Widget_Attrs($final_attrs).'>';
|
||||
$choices = array_merge($this->choices, $choices);
|
||||
foreach ($choices as $option_label=>$option_value) {
|
||||
$selected = (in_array($option_value, $value)) ? ' selected="selected"':'';
|
||||
$output[] = sprintf('<option value="%s"%s>%s</option>',
|
||||
htmlspecialchars($option_value, ENT_COMPAT, 'UTF-8'),
|
||||
$selected,
|
||||
htmlspecialchars($option_label, ENT_COMPAT, 'UTF-8'));
|
||||
|
||||
}
|
||||
$output[] = '</select>';
|
||||
return new Pluf_Template_SafeString(implode("\n", $output), true);
|
||||
}
|
||||
|
||||
public function valueFromFormData($name, $data)
|
||||
{
|
||||
if (isset($data[$name]) and is_array($data[$name])) {
|
||||
return $data[$name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
74
pluf/src/Pluf/Form/Widget/SelectMultipleInput/Checkbox.php
Normal file
74
pluf/src/Pluf/Form/Widget/SelectMultipleInput/Checkbox.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple checkbox.
|
||||
*/
|
||||
class Pluf_Form_Widget_SelectMultipleInput_Checkbox extends Pluf_Form_Widget_SelectMultipleInput
|
||||
{
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param array Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @param array Extra choices (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array(),
|
||||
$choices=array())
|
||||
{
|
||||
$output = array();
|
||||
if ($value === null or $value == '') {
|
||||
$value = array();
|
||||
}
|
||||
$final_attrs = $this->buildAttrs($extra_attrs);
|
||||
$output[] = '<ul>';
|
||||
$choices = array_merge($this->choices, $choices);
|
||||
$i=0;
|
||||
$base_id = $final_attrs['id'];
|
||||
foreach ($choices as $option_label=>$option_value) {
|
||||
|
||||
$final_attrs['id'] = $base_id.'_'.$i;
|
||||
$final_attrs['value'] = htmlspecialchars($option_value, ENT_COMPAT, 'UTF-8');
|
||||
$checkbox = new Pluf_Form_Widget_CheckboxInput($final_attrs);
|
||||
$rendered = $checkbox->render($name.'[]', in_array($option_value, $value));
|
||||
|
||||
$output[] = sprintf('<li><label>%s %s</label></li>', $rendered,
|
||||
htmlspecialchars($option_label, ENT_COMPAT, 'UTF-8'));
|
||||
$i++;
|
||||
}
|
||||
$output[] = '</ul>';
|
||||
return new Pluf_Template_SafeString(implode("\n", $output), true);
|
||||
}
|
||||
|
||||
public function idForLabel($id)
|
||||
{
|
||||
if ($id) {
|
||||
$id += '_0';
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
|
||||
}
|
30
pluf/src/Pluf/Form/Widget/TextInput.php
Normal file
30
pluf/src/Pluf/Form/Widget/TextInput.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Simple input of type text.
|
||||
*/
|
||||
class Pluf_Form_Widget_TextInput extends Pluf_Form_Widget_Input
|
||||
{
|
||||
public $input_type = 'text';
|
||||
}
|
55
pluf/src/Pluf/Form/Widget/TextareaInput.php
Normal file
55
pluf/src/Pluf/Form/Widget/TextareaInput.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Textarea.
|
||||
*/
|
||||
class Pluf_Form_Widget_TextareaInput extends Pluf_Form_Widget
|
||||
{
|
||||
|
||||
public function __construct($attrs=array())
|
||||
{
|
||||
$this->attrs = array_merge(array('cols' => '40', 'rows' => '10'),
|
||||
$attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
if ($value === null) $value = '';
|
||||
$final_attrs = $this->buildAttrs(array('name' => $name),
|
||||
$extra_attrs);
|
||||
return new Pluf_Template_SafeString(
|
||||
sprintf('<textarea%s>%s</textarea>',
|
||||
Pluf_Form_Widget_Attrs($final_attrs),
|
||||
htmlspecialchars($value, ENT_COMPAT, 'UTF-8')),
|
||||
true);
|
||||
}
|
||||
}
|
98
pluf/src/Pluf/Form/Widget/TinyMCEInput.php
Normal file
98
pluf/src/Pluf/Form/Widget/TinyMCEInput.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Textarea with TinyMCE addition.
|
||||
*/
|
||||
class Pluf_Form_Widget_TinyMCEInput extends Pluf_Form_Widget
|
||||
{
|
||||
public $tiny_mceurl = '/media/js/editor/tiny_mce.js';
|
||||
public $mode = 'textareas';
|
||||
public $theme = 'simple';
|
||||
public $include_tinymce = true;
|
||||
|
||||
public function __construct($attrs=array())
|
||||
{
|
||||
$defaults = array('cols' => '70',
|
||||
'rows' => '20');
|
||||
$config = array('tinymce_url', 'mode', 'theme', 'include_tinymce');
|
||||
foreach ($config as $cfg) {
|
||||
if (isset($attrs[$cfg])) {
|
||||
$this->$cfg = $attrs[$cfg];
|
||||
unset($attrs[$cfg]);
|
||||
}
|
||||
}
|
||||
$this->attrs = array_merge($defaults, $attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML of the input.
|
||||
*
|
||||
* @param string Name of the field.
|
||||
* @param mixed Value for the field, can be a non valid value.
|
||||
* @param array Extra attributes to add to the input form (array())
|
||||
* @return string The HTML string of the input.
|
||||
*/
|
||||
public function render($name, $value, $extra_attrs=array())
|
||||
{
|
||||
if ($value === null) $value = '';
|
||||
$extra_config = '';
|
||||
if (isset($this->attrs['editor_config'])) {
|
||||
$_ec = $this->attrs['editor_config'];
|
||||
unset($this->attrs['editor_config']);
|
||||
$_st = array();
|
||||
foreach ($_ec as $key=>$val) {
|
||||
if (is_bool($val)) {
|
||||
if ($val) {
|
||||
$_st[] = $key.' : true';
|
||||
} else {
|
||||
$_st[] = $key.' : false';
|
||||
}
|
||||
} else {
|
||||
$_st[] = $key.' : "'.$val.'"';
|
||||
}
|
||||
}
|
||||
if ($_st) {
|
||||
$extra_config = ",\n".implode(",\n", $_st);
|
||||
}
|
||||
}
|
||||
$final_attrs = $this->buildAttrs(array('name' => $name),
|
||||
$extra_attrs);
|
||||
// The special include for tinyMCE
|
||||
$out = '';
|
||||
if ($this->include_tinymce) {
|
||||
$out .= '<script language="javascript" type="text/javascript" src="'.$this->tinymce_url.'"></script>'."\n";
|
||||
}
|
||||
$out .='<script language="javascript" type="text/javascript">
|
||||
tinyMCE.init({
|
||||
mode : "'.$this->mode.'",
|
||||
theme : "'.$this->theme.'"'.$extra_config.'
|
||||
});
|
||||
</script>';
|
||||
return new Pluf_Template_SafeString(
|
||||
$out.sprintf('<textarea%s>%s</textarea>',
|
||||
Pluf_Form_Widget_Attrs($final_attrs),
|
||||
htmlspecialchars($value, ENT_COMPAT, 'UTF-8')),
|
||||
true);
|
||||
}
|
||||
}
|
90
pluf/src/Pluf/Group.php
Normal file
90
pluf/src/Pluf/Group.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_Group extends Pluf_Model
|
||||
{
|
||||
public $_model = 'Pluf_Group';
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->_a['verbose'] = __('group');
|
||||
$this->_a['table'] = 'groups';
|
||||
$this->_a['model'] = 'Pluf_Group';
|
||||
$this->_a['cols'] = array(
|
||||
// It is mandatory to have an "id" column.
|
||||
'id' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Sequence',
|
||||
//It is automatically added.
|
||||
'blank' => true,
|
||||
),
|
||||
'name' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Varchar',
|
||||
'blank' => false,
|
||||
'size' => 50,
|
||||
'verbose' => __('name'),
|
||||
),
|
||||
'description' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Varchar',
|
||||
'blank' => false,
|
||||
'size' => 250,
|
||||
'verbose' => __('description'),
|
||||
),
|
||||
'permissions' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Manytomany',
|
||||
'blank' => true,
|
||||
'model' => 'Pluf_Permission',
|
||||
),
|
||||
);
|
||||
if (Pluf::f('pluf_custom_group',false)) $this->extended_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for extended class
|
||||
*/
|
||||
function extended_init()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predelete to drop the row level permissions.
|
||||
*/
|
||||
function preDelete()
|
||||
{
|
||||
if (Pluf::f('pluf_use_rowpermission', false)) {
|
||||
$_rpt = Pluf::factory('Pluf_RowPermission')->getSqlTable();
|
||||
$sql = new Pluf_SQL('owner_class=%s AND owner_id=%s',
|
||||
array($this->_a['model'], $this->_data['id']));
|
||||
$this->_con->execute('DELETE FROM '.$_rpt.' WHERE '.$sql->gen());
|
||||
}
|
||||
}
|
||||
}
|
91
pluf/src/Pluf/HTTP.php
Normal file
91
pluf/src/Pluf/HTTP.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Base HTTP tools.
|
||||
*/
|
||||
class Pluf_HTTP
|
||||
{
|
||||
|
||||
/**
|
||||
* Break magic_quotes
|
||||
*
|
||||
* @credit Olivier Meunier
|
||||
*/
|
||||
function removeTheMagic()
|
||||
{
|
||||
if (get_magic_quotes_gpc()) {
|
||||
if (!empty($_GET)) {
|
||||
array_walk($_GET, 'Pluf_HTTP_magicStrip');
|
||||
}
|
||||
if (!empty($_POST)) {
|
||||
array_walk($_POST, 'Pluf_HTTP_magicStrip');
|
||||
}
|
||||
if (!empty($_REQUEST)) {
|
||||
array_walk($_REQUEST, 'Pluf_HTTP_magicStrip');
|
||||
}
|
||||
if (!empty($_COOKIE)) {
|
||||
array_walk($_COOKIE, 'Pluf_HTTP_magicStrip');
|
||||
}
|
||||
}
|
||||
if (function_exists('ini_set')) {
|
||||
@ini_set('session.use_cookies', '1');
|
||||
@ini_set('session.use_only_cookies', '1');
|
||||
@ini_set('session.use_trans_sid', '0');
|
||||
@ini_set('url_rewriter.tags', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Break magic_quotes
|
||||
*
|
||||
* @credit Olivier Meunier
|
||||
*/
|
||||
function Pluf_HTTP_magicStrip(&$k, $key)
|
||||
{
|
||||
$k = Pluf_HTTP_handleMagicQuotes($k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Break magic_quotes
|
||||
*
|
||||
* @credit Olivier Meunier
|
||||
*/
|
||||
function Pluf_HTTP_handleMagicQuotes(&$value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$result = array();
|
||||
foreach ($value as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$result[$k] = Pluf_HTTP_handleMagicQuotes($v);
|
||||
} else {
|
||||
$result[$k] = stripslashes($v);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
return stripslashes($value);
|
||||
}
|
||||
}
|
26
pluf/src/Pluf/HTTP/Error404.php
Normal file
26
pluf/src/Pluf/HTTP/Error404.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Error404 extends Exception
|
||||
{
|
||||
}
|
26
pluf/src/Pluf/HTTP/Error500.php
Normal file
26
pluf/src/Pluf/HTTP/Error500.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Error500 extends Exception
|
||||
{
|
||||
}
|
64
pluf/src/Pluf/HTTP/Request.php
Normal file
64
pluf/src/Pluf/HTTP/Request.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The request object.
|
||||
*
|
||||
* It is given as first arguments to the view as first argument.
|
||||
*/
|
||||
class Pluf_HTTP_Request
|
||||
{
|
||||
public $POST = array();
|
||||
public $GET = array();
|
||||
public $REQUEST = array();
|
||||
public $COOKIE = array();
|
||||
public $FILES = array();
|
||||
public $query = '';
|
||||
public $method = '';
|
||||
public $uri = '';
|
||||
public $view = '';
|
||||
public $remote_addr = '';
|
||||
public $http_host = '';
|
||||
public $SERVER = array();
|
||||
public $uid = '';
|
||||
public $time = '';
|
||||
|
||||
function __construct($query)
|
||||
{
|
||||
$http = new Pluf_HTTP();
|
||||
$http->removeTheMagic();
|
||||
$this->POST =& $_POST;
|
||||
$this->GET =& $_GET;
|
||||
$this->REQUEST =& $_REQUEST;
|
||||
$this->COOKIE =& $_COOKIE;
|
||||
$this->FILES =& $_FILES;
|
||||
$this->query = $query;
|
||||
$this->method = $_SERVER['REQUEST_METHOD'];
|
||||
$this->uri = $_SERVER['REQUEST_URI'];
|
||||
$this->remote_addr = $_SERVER['REMOTE_ADDR'];
|
||||
$this->http_host = (isset($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : '';
|
||||
$this->SERVER =& $_SERVER;
|
||||
$this->uid = $GLOBALS['_PX_uniqid'];
|
||||
$this->time = (isset($_SERVER['REQUEST_TIME'])) ? $_SERVER['REQUEST_TIME'] : time();
|
||||
}
|
||||
}
|
174
pluf/src/Pluf/HTTP/Response.php
Normal file
174
pluf/src/Pluf/HTTP/Response.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Response object to be constructed by the views.
|
||||
*
|
||||
* When constructing a view, the response object must be populated and
|
||||
* returned. The response is then displayed to the visitor.
|
||||
* The interest of using a response object is that we can run a post
|
||||
* filter action on the response. For example you can run a filter that
|
||||
* is checking that all the output is valid HTML and write a logfile if
|
||||
* this is not the case.
|
||||
*/
|
||||
class Pluf_HTTP_Response
|
||||
{
|
||||
/**
|
||||
* Content of the response.
|
||||
*/
|
||||
public $content = '';
|
||||
|
||||
/**
|
||||
* Array of the headers to add.
|
||||
*
|
||||
* For example $this->headers['Content-Type'] = 'text/html; charset=utf-8';
|
||||
*/
|
||||
public $headers = array();
|
||||
|
||||
/**
|
||||
* Status code of the answer.
|
||||
*/
|
||||
public $status_code = 200;
|
||||
|
||||
/**
|
||||
* Cookies to send.
|
||||
*
|
||||
* $this->cookies['my_cookie'] = 'content of the cookie';
|
||||
*/
|
||||
public $cookies = array();
|
||||
|
||||
/**
|
||||
* Status code list.
|
||||
*
|
||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
*/
|
||||
public $status_code_list = array(
|
||||
'100' => 'CONTINUE',
|
||||
'101' => 'SWITCHING PROTOCOLS',
|
||||
'200' => 'OK',
|
||||
'201' => 'CREATED',
|
||||
'202' => 'ACCEPTED',
|
||||
'203' => 'NON-AUTHORITATIVE INFORMATION',
|
||||
'204' => 'NO CONTENT',
|
||||
'205' => 'RESET CONTENT',
|
||||
'206' => 'PARTIAL CONTENT',
|
||||
'300' => 'MULTIPLE CHOICES',
|
||||
'301' => 'MOVED PERMANENTLY',
|
||||
'302' => 'FOUND',
|
||||
'303' => 'SEE OTHER',
|
||||
'304' => 'NOT MODIFIED',
|
||||
'305' => 'USE PROXY',
|
||||
'306' => 'RESERVED',
|
||||
'307' => 'TEMPORARY REDIRECT',
|
||||
'400' => 'BAD REQUEST',
|
||||
'401' => 'UNAUTHORIZED',
|
||||
'402' => 'PAYMENT REQUIRED',
|
||||
'403' => 'FORBIDDEN',
|
||||
'404' => 'NOT FOUND',
|
||||
'405' => 'METHOD NOT ALLOWED',
|
||||
'406' => 'NOT ACCEPTABLE',
|
||||
'407' => 'PROXY AUTHENTICATION REQUIRED',
|
||||
'408' => 'REQUEST TIMEOUT',
|
||||
'409' => 'CONFLICT',
|
||||
'410' => 'GONE',
|
||||
'411' => 'LENGTH REQUIRED',
|
||||
'412' => 'PRECONDITION FAILED',
|
||||
'413' => 'REQUEST ENTITY TOO LARGE',
|
||||
'414' => 'REQUEST-URI TOO LONG',
|
||||
'415' => 'UNSUPPORTED MEDIA TYPE',
|
||||
'416' => 'REQUESTED RANGE NOT SATISFIABLE',
|
||||
'417' => 'EXPECTATION FAILED',
|
||||
'500' => 'INTERNAL SERVER ERROR',
|
||||
'501' => 'NOT IMPLEMENTED',
|
||||
'502' => 'BAD GATEWAY',
|
||||
'503' => 'SERVICE UNAVAILABLE',
|
||||
'504' => 'GATEWAY TIMEOUT',
|
||||
'505' => 'HTTP VERSION NOT SUPPORTED'
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Constructor of the response.
|
||||
*
|
||||
* @param string Content of the response ('')
|
||||
* @param string MimeType of the response (null) if not given will
|
||||
* default to the one given in the configuration 'mimetype'
|
||||
*/
|
||||
function __construct($content='', $mimetype=null)
|
||||
{
|
||||
if (is_null($mimetype)) {
|
||||
$mimetype = Pluf::f('mimetype', 'text/html').'; charset=utf-8';
|
||||
}
|
||||
$this->content = $content;
|
||||
$this->headers['Content-Type'] = $mimetype;
|
||||
$this->headers['X-Powered-By'] = 'Pluf - http://pluf.org/';
|
||||
$this->status_code = 200;
|
||||
$this->cookies = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a response object.
|
||||
*/
|
||||
function render($output_body=true)
|
||||
{
|
||||
if ($this->status_code >= 200
|
||||
&& $this->status_code != 204
|
||||
&& $this->status_code != 304) {
|
||||
$this->headers['Content-Length'] = strlen($this->content);
|
||||
}
|
||||
$this->outputHeaders();
|
||||
if ($output_body) {
|
||||
echo $this->content;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output headers.
|
||||
*/
|
||||
function outputHeaders()
|
||||
{
|
||||
if (!defined('IN_UNIT_TESTS')) {
|
||||
header('HTTP/1.0 '.$this->status_code.' '
|
||||
.$this->status_code_list[$this->status_code],
|
||||
true, $this->status_code);
|
||||
foreach ($this->headers as $header => $ch) {
|
||||
header($header.': '.$ch);
|
||||
}
|
||||
foreach ($this->cookies as $cookie => $data) {
|
||||
// name, data, expiration, path, domain, secure, http only
|
||||
$expire = (null == $data) ? time()-31536000 : time()+31536000;
|
||||
$data = (null == $data) ? '' : $data;
|
||||
setcookie($cookie, $data, $expire,
|
||||
Pluf::f('cookie_path', '/'),
|
||||
Pluf::f('cookie_domain', null),
|
||||
Pluf::f('cookie_secure', false),
|
||||
Pluf::f('cookie_httponly', true));
|
||||
}
|
||||
} else {
|
||||
$_COOKIE = array();
|
||||
foreach ($this->cookies as $cookie => $data) {
|
||||
$_COOKIE[$cookie] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
54
pluf/src/Pluf/HTTP/Response/CommandPassThru.php
Normal file
54
pluf/src/Pluf/HTTP/Response/CommandPassThru.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Special response object to output the return value of a command.
|
||||
*
|
||||
* You need to use escapeshellarg() and escapeshellcmd() to provide a
|
||||
* "clean" command. The Content-Length will not be set as it is not
|
||||
* possible to predict it.
|
||||
*/
|
||||
class Pluf_HTTP_Response_CommandPassThru extends Pluf_HTTP_Response
|
||||
{
|
||||
/**
|
||||
* The command argument must be a safe string!
|
||||
*
|
||||
* @param string Command to run.
|
||||
* @param string Mimetype (null)
|
||||
*/
|
||||
function __construct($command, $mimetype=null)
|
||||
{
|
||||
parent::__construct($command, $mimetype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a response object.
|
||||
*/
|
||||
function render($output_body=true)
|
||||
{
|
||||
$this->outputHeaders();
|
||||
if ($output_body) {
|
||||
passthru($this->content);
|
||||
}
|
||||
}
|
||||
}
|
50
pluf/src/Pluf/HTTP/Response/File.php
Normal file
50
pluf/src/Pluf/HTTP/Response/File.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_File extends Pluf_HTTP_Response
|
||||
{
|
||||
public $delete_file = false;
|
||||
|
||||
function __construct($filepath, $mimetype=null, $delete_file=false)
|
||||
{
|
||||
parent::__construct($filepath, $mimetype);
|
||||
$this->delete_file = $delete_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a response object.
|
||||
*/
|
||||
function render($output_body=true)
|
||||
{
|
||||
$this->headers['Content-Length'] = (string)filesize($this->content);
|
||||
$this->outputHeaders();
|
||||
if ($output_body) {
|
||||
$fp = fopen($this->content, 'rb');
|
||||
fpassthru($fp);
|
||||
fclose($fp);
|
||||
}
|
||||
if ($this->delete_file) {
|
||||
@unlink($this->content);
|
||||
}
|
||||
}
|
||||
}
|
42
pluf/src/Pluf/HTTP/Response/Forbidden.php
Normal file
42
pluf/src/Pluf/HTTP/Response/Forbidden.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_Forbidden extends Pluf_HTTP_Response
|
||||
{
|
||||
function __construct($request)
|
||||
{
|
||||
$content = '';
|
||||
try {
|
||||
$context = new Pluf_Template_Context(array('query' => $request->query));
|
||||
$tmpl = new Pluf_Template('403.html');
|
||||
$content = $tmpl->render($context);
|
||||
$mimetype = null;
|
||||
} catch (Exception $e) {
|
||||
$mimetype = 'text/plain';
|
||||
$content = 'You are not authorized to view this page. You do not have permission'."\n"
|
||||
.'to view the requested directory or page using the credentials supplied.'."\n\n".'403 - Forbidden';
|
||||
}
|
||||
parent::__construct($content, $mimetype);
|
||||
$this->status_code = 403;
|
||||
}
|
||||
}
|
36
pluf/src/Pluf/HTTP/Response/Json.php
Normal file
36
pluf/src/Pluf/HTTP/Response/Json.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_Json extends Pluf_HTTP_Response
|
||||
{
|
||||
/**
|
||||
* @param mixed Values, will be encoded using json_encode
|
||||
*/
|
||||
function __construct($data, $mimetype=null)
|
||||
{
|
||||
if (null == $mimetype) {
|
||||
$mimetype = Pluf::f('mimetype_json', 'application/json').'; charset=utf-8';
|
||||
}
|
||||
parent::__construct(json_encode($data), $mimetype);
|
||||
}
|
||||
}
|
44
pluf/src/Pluf/HTTP/Response/NotAvailable.php
Normal file
44
pluf/src/Pluf/HTTP/Response/NotAvailable.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_NotAvailable extends Pluf_HTTP_Response
|
||||
{
|
||||
function __construct($request)
|
||||
{
|
||||
$content = '';
|
||||
try {
|
||||
$context = new Pluf_Template_Context(array('query' => $request->query));
|
||||
$tmpl = new Pluf_Template('503.html');
|
||||
$content = $tmpl->render($context);
|
||||
$mimetype = null;
|
||||
} catch (Exception $e) {
|
||||
$mimetype = 'text/plain';
|
||||
$content = sprintf('The requested URL %s is not available at the moment.'."\n"
|
||||
.'Please try again later.'."\n\n".'503 - Service Unavailable',
|
||||
Pluf_esc($request->query));
|
||||
}
|
||||
parent::__construct($content, $mimetype);
|
||||
$this->status_code = 503;
|
||||
$this->headers['Retry-After'] = 300; // retry after 5 minutes
|
||||
}
|
||||
}
|
43
pluf/src/Pluf/HTTP/Response/NotFound.php
Normal file
43
pluf/src/Pluf/HTTP/Response/NotFound.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_NotFound extends Pluf_HTTP_Response
|
||||
{
|
||||
function __construct($request)
|
||||
{
|
||||
$content = '';
|
||||
try {
|
||||
$context = new Pluf_Template_Context(array('query' => $request->query));
|
||||
$tmpl = new Pluf_Template('404.html');
|
||||
$content = $tmpl->render($context);
|
||||
$mimetype = null;
|
||||
} catch (Exception $e) {
|
||||
$mimetype = 'text/plain';
|
||||
$content = sprintf('The requested URL %s was not found on this server.'."\n"
|
||||
.'Please check the URL and try again.'."\n\n".'404 - Not Found',
|
||||
Pluf_esc($request->query));
|
||||
}
|
||||
parent::__construct($content, $mimetype);
|
||||
$this->status_code = 404;
|
||||
}
|
||||
}
|
39
pluf/src/Pluf/HTTP/Response/Redirect.php
Normal file
39
pluf/src/Pluf/HTTP/Response/Redirect.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_Redirect extends Pluf_HTTP_Response
|
||||
{
|
||||
/**
|
||||
* Redirect response to a given URL.
|
||||
*
|
||||
* @param string URL
|
||||
* @paran int Redirect code (302) or 301 for permanent
|
||||
*/
|
||||
function __construct($url, $code=302)
|
||||
{
|
||||
$content = sprintf(__('<a href="%s">Please, click here to be redirected</a>.'), $url);
|
||||
parent::__construct($content);
|
||||
$this->headers['Location'] = $url;
|
||||
$this->status_code = $code;
|
||||
}
|
||||
}
|
61
pluf/src/Pluf/HTTP/Response/RedirectToLogin.php
Normal file
61
pluf/src/Pluf/HTTP/Response/RedirectToLogin.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Can be used as a response to return when a user must be logged to
|
||||
* access a page.
|
||||
*/
|
||||
class Pluf_HTTP_Response_RedirectToLogin extends Pluf_HTTP_Response
|
||||
{
|
||||
/**
|
||||
* The $request object is used to know what the post login
|
||||
* redirect url should be.
|
||||
*
|
||||
* If the action url of the login page is not set, it will try to
|
||||
* get the url from the login view from the 'login_view'
|
||||
* configuration key.
|
||||
*
|
||||
* @param Pluf_HTTP_Request The request object of the current page.
|
||||
* @param string The full url of the login page (null)
|
||||
*/
|
||||
function __construct($request, $loginurl=null)
|
||||
{
|
||||
if ($loginurl !== null) {
|
||||
$murl = new Pluf_HTTP_URL();
|
||||
$url = $murl->generate($loginurl, array('_redirect_after' => $request->uri), false);
|
||||
$encoded = $murl->generate($loginurl, array('_redirect_after' => $request->uri));
|
||||
} else {
|
||||
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
|
||||
$url = Pluf_HTTP_URL_urlForView(Pluf::f('login_view', 'login_view'),
|
||||
array(),
|
||||
array('_redirect_after' => $request->uri), false);
|
||||
$encoded = Pluf_HTTP_URL_urlForView(Pluf::f('login_view', 'login_view'),
|
||||
array(),
|
||||
array('_redirect_after' => $request->uri));
|
||||
}
|
||||
$content = sprintf(__('<a href="%s">Please, click here to be redirected</a>.'), $encoded);
|
||||
parent::__construct($content);
|
||||
$this->headers['Location'] = $url;
|
||||
$this->status_code = 302;
|
||||
}
|
||||
}
|
171
pluf/src/Pluf/HTTP/Response/ServerError.php
Normal file
171
pluf/src/Pluf/HTTP/Response/ServerError.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_ServerError extends Pluf_HTTP_Response
|
||||
{
|
||||
function __construct($exception, $mimetype=null)
|
||||
{
|
||||
$content = '';
|
||||
$admins = Pluf::f('admins', array());
|
||||
if (count($admins) > 0) {
|
||||
// Get a nice stack trace and send it by emails.
|
||||
$stack = Pluf_HTTP_Response_ServerError_Pretty($exception);
|
||||
$subject = $exception->getMessage();
|
||||
$subject = substr(strip_tags(nl2br($subject)), 0, 50).'...';
|
||||
foreach ($admins as $admin) {
|
||||
$email = new Pluf_Mail($admin[1], $admin[1], $subject);
|
||||
$email->addTextMessage($stack);
|
||||
$email->sendMail();
|
||||
}
|
||||
}
|
||||
try {
|
||||
$context = new Pluf_Template_Context(array('message' => $exception->getMessage()));
|
||||
$tmpl = new Pluf_Template('500.html');
|
||||
$content = $tmpl->render($context);
|
||||
$mimetype = null;
|
||||
} catch (Exception $e) {
|
||||
$mimetype = 'text/plain';
|
||||
$content = 'The server encountered an unexpected condition which prevented it from fulfilling your request.'."\n\n"
|
||||
.'An email has been sent to the administrators, we will correct this error as soon as possible. Thank you for your comprehension.'
|
||||
."\n\n".'500 - Internal Server Error';
|
||||
}
|
||||
parent::__construct($content, $mimetype);
|
||||
$this->status_code = 500;
|
||||
}
|
||||
}
|
||||
|
||||
function Pluf_HTTP_Response_ServerError_Pretty($e)
|
||||
{
|
||||
$sub = create_function('$f','$loc="";if(isset($f["class"])){
|
||||
$loc.=$f["class"].$f["type"];}
|
||||
if(isset($f["function"])){$loc.=$f["function"];}
|
||||
return $loc;');
|
||||
$parms = create_function('$f','$params=array();if(isset($f["function"])){
|
||||
try{if(isset($f["class"])){
|
||||
$r=new ReflectionMethod($f["class"]."::".$f["function"]);}
|
||||
else{$r=new ReflectionFunction($f["function"]);}
|
||||
return $r->getParameters();}catch(Exception $e){}}
|
||||
return $params;');
|
||||
$src2lines = create_function('$file','$src=nl2br(highlight_file($file,TRUE));
|
||||
return explode("<br />",$src);');
|
||||
$clean = create_function('$line','return html_entity_decode(str_replace(" ", " ", $line));');
|
||||
$desc = get_class($e)." making ".$_SERVER['REQUEST_METHOD']." request to ".$_SERVER['REQUEST_URI'];
|
||||
$out = $desc."\n";
|
||||
if ($e->getCode()) {
|
||||
$out .= $e->getCode(). ' : ';
|
||||
}
|
||||
$out .= $e->getMessage()."\n\n";
|
||||
$out .= 'PHP: '.$e->getFile().', line '.$e->getLine()."\n";
|
||||
$out .= 'URI: '.$_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI']."\n\n";
|
||||
$out .= '** Stacktrace **'."\n\n";
|
||||
$frames = $e->getTrace();
|
||||
foreach ($frames as $frame_id=>$frame) {
|
||||
if (!isset($frame['file'])) {
|
||||
$frame['file'] = 'No File';
|
||||
$frame['line'] = '0';
|
||||
}
|
||||
$out .= '* '.$sub($frame).'
|
||||
['.$frame['file'].', line '.$frame['line'].'] *'."\n";
|
||||
if (is_readable($frame['file']) ) {
|
||||
$out .= '* Src *'."\n";
|
||||
$lines = $src2lines($frame['file']);
|
||||
$start = $frame['line'] < 5 ?
|
||||
0 : $frame['line'] -5; $end = $start + 10;
|
||||
$out2 = '';
|
||||
$i = 0;
|
||||
foreach ( $lines as $k => $line ) {
|
||||
if ( $k > $end ) { break; }
|
||||
$line = trim(strip_tags($line));
|
||||
if ( $k < $start && isset($frames[$frame_id+1]["function"])
|
||||
&& preg_match('/function( )*'.preg_quote($frames[$frame_id+1]["function"]).'/',
|
||||
$line) ) {
|
||||
$start = $k;
|
||||
}
|
||||
if ( $k >= $start ) {
|
||||
if ( $k != $frame['line'] ) {
|
||||
$out2 .= ($start+$i).': '.$clean($line)."\n";
|
||||
} else {
|
||||
$out2 .= '>> '.($start+$i).': '.$clean($line)."\n";
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$out .= $out2;
|
||||
} else {
|
||||
$out .= 'No src available.';
|
||||
}
|
||||
$out .= "\n";
|
||||
}
|
||||
$out .= "\n\n\n\n";
|
||||
$out .= '** Request **'."\n\n";
|
||||
|
||||
if ( function_exists('apache_request_headers') ) {
|
||||
$out .= '* Request (raw) *'."\n\n";
|
||||
$req_headers = apache_request_headers();
|
||||
$out .= 'HEADERS'."\n";
|
||||
if ( count($req_headers) > 0 ) {
|
||||
foreach ($req_headers as $req_h_name => $req_h_val) {
|
||||
$out .= $req_h_name.': '.$req_h_val."\n";
|
||||
}
|
||||
$out .= "\n";
|
||||
} else {
|
||||
$out .= 'No headers.'."\n";
|
||||
}
|
||||
$req_body = file_get_contents('php://input');
|
||||
if ( strlen( $req_body ) > 0 ) {
|
||||
$out .= 'Body'."\n";
|
||||
$out .= $req_body."\n";
|
||||
}
|
||||
}
|
||||
$out .= "\n".'* Request (parsed) *'."\n\n";
|
||||
$superglobals = array('$_GET','$_POST','$_COOKIE','$_SERVER','$_ENV');
|
||||
foreach ( $superglobals as $sglobal ) {
|
||||
$sfn = create_function('','return '.$sglobal.';');
|
||||
$out .= $sglobal."\n";
|
||||
if ( count($sfn()) > 0 ) {
|
||||
foreach ( $sfn() as $k => $v ) {
|
||||
$out .= 'Variable: '.$k."\n";
|
||||
$out .= 'Value: '.print_r($v,TRUE)."\n";
|
||||
}
|
||||
$out .= "\n";
|
||||
} else {
|
||||
$out .= 'No data'."\n\n";
|
||||
}
|
||||
}
|
||||
if ( function_exists('headers_list') ) {
|
||||
$out .= "\n\n\n\n";
|
||||
$out .= '** Response **'."\n\n";
|
||||
$out .= '* Headers *'."\n\n";
|
||||
$resp_headers = headers_list();
|
||||
if (count($resp_headers) > 0) {
|
||||
foreach ( $resp_headers as $resp_h ) {
|
||||
$out .= $resp_h."\n";
|
||||
}
|
||||
$out .= "\n";
|
||||
} else {
|
||||
$out .= 'No headers.'."\n";
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
376
pluf/src/Pluf/HTTP/Response/ServerErrorDebug.php
Normal file
376
pluf/src/Pluf/HTTP/Response/ServerErrorDebug.php
Normal file
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of Plume Framework, a simple PHP Application Framework.
|
||||
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
|
||||
#
|
||||
# Plume Framework is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Plume Framework 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class Pluf_HTTP_Response_ServerErrorDebug extends Pluf_HTTP_Response
|
||||
{
|
||||
/**
|
||||
* Debug version of a server error.
|
||||
*
|
||||
* @param Exception The exception being raised.
|
||||
* @param string Mime type
|
||||
*/
|
||||
function __construct($e, $mimetype=null)
|
||||
{
|
||||
$this->status_code = 500;
|
||||
$this->content = Pluf_HTTP_Response_ServerErrorDebug_Pretty($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @credits http://www.sitepoint.com/blogs/2006/04/04/pretty-blue-screen/
|
||||
*/
|
||||
function Pluf_HTTP_Response_ServerErrorDebug_Pretty($e)
|
||||
{
|
||||
$o = create_function('$in','return htmlspecialchars($in);');
|
||||
$sub = create_function('$f','$loc="";if(isset($f["class"])){
|
||||
$loc.=$f["class"].$f["type"];}
|
||||
if(isset($f["function"])){$loc.=$f["function"];}
|
||||
if(!empty($loc)){$loc=htmlspecialchars($loc);
|
||||
$loc="<strong>$loc</strong>";}return $loc;');
|
||||
$parms = create_function('$f','$params=array();if(isset($f["function"])){
|
||||
try{if(isset($f["class"])){
|
||||
$r=new ReflectionMethod($f["class"]."::".$f["function"]);}
|
||||
else{$r=new ReflectionFunction($f["function"]);}
|
||||
return $r->getParameters();}catch(Exception $e){}}
|
||||
return $params;');
|
||||
$src2lines = create_function('$file','$src=nl2br(highlight_file($file,TRUE));
|
||||
return explode("<br />",$src);');
|
||||
$clean = create_function('$line','return trim(strip_tags($line));');
|
||||
$desc = get_class($e)." making ".$_SERVER['REQUEST_METHOD']." request to ".
|
||||
$_SERVER['REQUEST_URI'];
|
||||
$out = '
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="robots" content="NONE,NOARCHIVE" />
|
||||
<title>'.$o($desc).'</title>
|
||||
<style type="text/css">
|
||||
html * { padding:0; margin:0; }
|
||||
body * { padding:10px 20px; }
|
||||
body * * { padding:0; }
|
||||
body { font:small sans-serif; background: #70DBFF; }
|
||||
body>div { border-bottom:1px solid #ddd; }
|
||||
h1 { font-weight:normal; }
|
||||
h2 { margin-bottom:.8em; }
|
||||
h2 span { font-size:80%; color:#666; font-weight:normal; }
|
||||
h2 a { text-decoration:none; }
|
||||
h3 { margin:1em 0 .5em 0; }
|
||||
h4 { margin:0.5em 0 .5em 0; font-weight: normal; font-style: italic; }
|
||||
table {
|
||||
border:1px solid #ccc; border-collapse: collapse; background:white; }
|
||||
tbody td, tbody th { vertical-align:top; padding:2px 3px; }
|
||||
thead th {
|
||||
padding:1px 6px 1px 3px; background:#70FF94; text-align:left;
|
||||
font-weight:bold; font-size:11px; border:1px solid #ddd; }
|
||||
tbody th { text-align:right; color:#666; padding-right:.5em; }
|
||||
table.vars { margin:5px 0 2px 40px; }
|
||||
table.vars td, table.req td { font-family:monospace; }
|
||||
table td { background: #70FFDB; }
|
||||
table td.code { width:95%;}
|
||||
table td.code div { overflow:hidden; }
|
||||
table.source th { color:#666; }
|
||||
table.source td {
|
||||
font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
|
||||
ul.traceback { list-style-type:none; }
|
||||
ul.traceback li.frame { margin-bottom:1em; }
|
||||
div.context { margin:5px 0 2px 40px; background-color:#70FFDB; }
|
||||
div.context ol {
|
||||
padding-left:30px; margin:0 10px; list-style-position: inside; }
|
||||
div.context ol li {
|
||||
font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
|
||||
div.context li.current-line { color:black; background-color:#70FF94; }
|
||||
div.commands { margin-left: 40px; }
|
||||
div.commands a { color:black; text-decoration:none; }
|
||||
p.headers { background: #70FFDB; font-family:monospace; }
|
||||
#summary { background: #00B8F5; }
|
||||
#summary h2 { font-weight: normal; color: #666; }
|
||||
#traceback { background:#eee; }
|
||||
#request { background:#f6f6f6; }
|
||||
#response { background:#eee; }
|
||||
#summary table { border:none; background:#00B8F5; }
|
||||
#summary td { background:#00B8F5; }
|
||||
.switch { text-decoration: none; }
|
||||
.whitemsg { background:white; color:black;}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<!--
|
||||
function getElementsByClassName(oElm, strTagName, strClassName){
|
||||
// Written by Jonathan Snook, http://www.snook.ca/jon;
|
||||
// Add-ons by Robert Nyman, http://www.robertnyman.com
|
||||
var arrElements = (strTagName == "*" && document.all)? document.all :
|
||||
oElm.getElementsByTagName(strTagName);
|
||||
var arrReturnElements = new Array();
|
||||
strClassName = strClassName.replace(/\-/g, "\\-");
|
||||
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
|
||||
var oElement;
|
||||
for(var i=0; i<arrElements.length; i++){
|
||||
oElement = arrElements[i];
|
||||
if(oRegExp.test(oElement.className)){
|
||||
arrReturnElements.push(oElement);
|
||||
}
|
||||
}
|
||||
return (arrReturnElements)
|
||||
}
|
||||
function hideAll(elems) {
|
||||
for (var e = 0; e < elems.length; e++) {
|
||||
elems[e].style.display = \'none\';
|
||||
}
|
||||
}
|
||||
function toggle() {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var e = document.getElementById(arguments[i]);
|
||||
if (e) {
|
||||
e.style.display = e.style.display == \'none\' ? \'block\' : \'none\';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function varToggle(link, id, prefix) {
|
||||
toggle(prefix + id);
|
||||
var s = link.getElementsByTagName(\'span\')[0];
|
||||
var uarr = String.fromCharCode(0x25b6);
|
||||
var darr = String.fromCharCode(0x25bc);
|
||||
s.innerHTML = s.innerHTML == uarr ? darr : uarr;
|
||||
return false;
|
||||
}
|
||||
function sectionToggle(span, section) {
|
||||
toggle(section);
|
||||
var span = document.getElementById(span);
|
||||
var uarr = String.fromCharCode(0x25b6);
|
||||
var darr = String.fromCharCode(0x25bc);
|
||||
span.innerHTML = span.innerHTML == uarr ? darr : uarr;
|
||||
return false;
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
hideAll(getElementsByClassName(document, \'table\', \'vars\'));
|
||||
hideAll(getElementsByClassName(document, \'div\', \'context\'));
|
||||
hideAll(getElementsByClassName(document, \'ul\', \'traceback\'));
|
||||
hideAll(getElementsByClassName(document, \'div\', \'section\'));
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="summary">
|
||||
<h1>'.$o($desc).'</h1>
|
||||
<h2>';
|
||||
if ($e->getCode()) {
|
||||
$out .= $o($e->getCode()). ' : ';
|
||||
}
|
||||
$out .= ' '.$o($e->getMessage()).'</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>PHP</th>
|
||||
<td>'.$o($e->getFile()).', line '.$o($e->getLine()).'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>URI</th>
|
||||
<td>'.$o($_SERVER['REQUEST_METHOD'].' '.
|
||||
$_SERVER['REQUEST_URI']).'</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="traceback">
|
||||
<h2>Stacktrace
|
||||
<a href=\'#\' onclick="return sectionToggle(\'tb_switch\',\'tb_list\')">
|
||||
<span id="tb_switch">▶</span></a></h2>
|
||||
<ul id="tb_list" class="traceback">';
|
||||
$frames = $e->getTrace();
|
||||
foreach ($frames as $frame_id=>$frame) {
|
||||
if (!isset($frame['file'])) {
|
||||
$frame['file'] = 'No File';
|
||||
$frame['line'] = '0';
|
||||
}
|
||||
$out .= '<li class="frame">'.$sub($frame).'
|
||||
['.$o($frame['file']).', line '.$o($frame['line']).']';
|
||||
if (isset($frame['args']) && count($frame['args']) > 0) {
|
||||
$params = $parms($frame);
|
||||
$out .= '
|
||||
<div class="commands">
|
||||
<a href=\'#\' onclick="return varToggle(this, \''.
|
||||
$o($frame_id).'\',\'v\')"><span>▶</span> Args</a>
|
||||
</div>
|
||||
<table class="vars" id="v'.$o($frame_id).'">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Arg</th>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
foreach ($frame['args'] as $k => $v) {
|
||||
$name = (isset($params[$k]) and isset($params[$k]->name)) ? '$'.$params[$k]->name : '?';
|
||||
$out .= '
|
||||
<tr>
|
||||
<td>'.$o($k).'</td>
|
||||
<td>'.$o($name).'</td>
|
||||
<td class="code">
|
||||
<pre>'.Pluf_esc(print_r($v, true)).'</pre>
|
||||
</td>
|
||||
</tr>';
|
||||
}
|
||||
$out .= '</tbody></table>';
|
||||
}
|
||||
if (is_readable($frame['file']) ) {
|
||||
$out .= '
|
||||
<div class="commands">
|
||||
<a href=\'#\' onclick="return varToggle(this, \''
|
||||
.$o($frame_id).'\',\'c\')"><span>▶</span> Src</a>
|
||||
</div>
|
||||
<div class="context" id="c'.$o($frame_id).'">';
|
||||
$lines = $src2lines($frame['file']);
|
||||
$start = $frame['line'] < 5 ?
|
||||
0 : $frame['line'] -5; $end = $start + 10;
|
||||
$out2 = '';
|
||||
foreach ( $lines as $k => $line ) {
|
||||
if ( $k > $end ) { break; }
|
||||
$line = trim(strip_tags($line));
|
||||
if ( $k < $start && isset($frames[$frame_id+1]["function"])
|
||||
&& preg_match('/function( )*'.preg_quote($frames[$frame_id+1]["function"]).'/',
|
||||
$line) ) {
|
||||
$start = $k;
|
||||
}
|
||||
if ( $k >= $start ) {
|
||||
if ( $k != $frame['line'] ) {
|
||||
$out2 .= '<li><code>'.$clean($line).'</code></li>'."\n"; }
|
||||
else {
|
||||
$out2 .= '<li class="current-line"><code>'.
|
||||
$clean($line).'</code></li>'."\n"; }
|
||||
}
|
||||
}
|
||||
$out .= "<ol start=\"$start\">\n".$out2. "</ol>\n";
|
||||
$out .= '</div>';
|
||||
} else {
|
||||
$out .= '<div class="commands">No src available</div>';
|
||||
}
|
||||
$out .= '</li>';
|
||||
} // End of foreach $frames
|
||||
$out .= '
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="request">
|
||||
<h2>Request
|
||||
<a href=\'#\' onclick="return sectionToggle(\'req_switch\',\'req_list\')">
|
||||
<span id="req_switch">▶</span></a></h2>
|
||||
<div id="req_list" class="section">';
|
||||
if ( function_exists('apache_request_headers') ) {
|
||||
$out .= '<h3>Request <span>(raw)</span></h3>';
|
||||
$req_headers = apache_request_headers();
|
||||
$out .= '<h4>HEADERS</h4>';
|
||||
if ( count($req_headers) > 0 ) {
|
||||
$out .= '<p class="headers">';
|
||||
foreach ($req_headers as $req_h_name => $req_h_val) {
|
||||
$out .= $o($req_h_name.': '.$req_h_val);
|
||||
$out .= '<br>';
|
||||
}
|
||||
$out .= '</p>';
|
||||
} else {
|
||||
$out .= '<p>No headers.</p>';
|
||||
}
|
||||
$req_body = file_get_contents('php://input');
|
||||
if ( strlen( $req_body ) > 0 ) {
|
||||
$out .='
|
||||
<h4>Body</h4>
|
||||
<p class="req" style="padding-bottom: 2em"><code>
|
||||
'.$o($req_body).'
|
||||
</code></p>';
|
||||
}
|
||||
}
|
||||
$out .= '
|
||||
<h3>Request <span>(parsed)</span></h3>';
|
||||
$superglobals = array('$_GET','$_POST','$_COOKIE','$_SERVER','$_ENV');
|
||||
foreach ( $superglobals as $sglobal ) {
|
||||
$sfn = create_function('','return '.$sglobal.';');
|
||||
$out .= '<h4>'.$sglobal.'</h4>';
|
||||
if ( count($sfn()) > 0 ) {
|
||||
$out .= '
|
||||
<table class="req">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Variable</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
foreach ( $sfn() as $k => $v ) {
|
||||
$out .= '<tr>
|
||||
<td>'.$o($k).'</td>
|
||||
<td class="code">
|
||||
<div>'.$o(print_r($v,TRUE)).'</div>
|
||||
</td>
|
||||
</tr>';
|
||||
}
|
||||
$out .= '
|
||||
</tbody>
|
||||
</table>';
|
||||
} else {
|
||||
$out .= '
|
||||
<p class="whitemsg">No data</p>';
|
||||
}
|
||||
}
|
||||
$out .= '
|
||||
|
||||
</div>
|
||||
</div>';
|
||||
if ( function_exists('headers_list') ) {
|
||||
$out .= '
|
||||
<div id="response">
|
||||
|
||||
<h2>Response
|
||||
<a href=\'#\' onclick="return sectionToggle(\'resp_switch\',\'resp_list\')">
|
||||
<span id="resp_switch">▶</span></a></h2>
|
||||
|
||||
<div id="resp_list" class="section">
|
||||
|
||||
<h3>Headers</h3>';
|
||||
$resp_headers = headers_list();
|
||||
if (count($resp_headers) > 0) {
|
||||
$out .= '
|
||||
<p class="headers">';
|
||||
foreach ( $resp_headers as $resp_h ) {
|
||||
$out .= $o($resp_h);
|
||||
$out .= '<br>';
|
||||
}
|
||||
$out .= ' </p>';
|
||||
} else {
|
||||
$out .= '
|
||||
<p>No headers.</p>';
|
||||
}
|
||||
$out .= '
|
||||
</div>';
|
||||
}
|
||||
$out .= '
|
||||
</body>
|
||||
</html>
|
||||
';
|
||||
return $out;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user