Merge lp:~quam-plures-core/quam-plures/qp5_next_branch into lp:quam-plures

Proposed by EdB
Status: Merged
Merged at revision: 7661
Proposed branch: lp:~quam-plures-core/quam-plures/qp5_next_branch
Merge into: lp:quam-plures
Diff against target: 63542 lines (+22188/-23862)
219 files modified
a_notemplate.php (+0/-1)
admin.php (+69/-120)
qp_config/_advanced.php (+1/-1)
qp_config/_locales.php (+1/-1)
qp_config/_upgrade.php (+0/-28)
qp_inc/_application.php (+1/-1)
qp_inc/_core/__core.init.php (+30/-19)
qp_inc/_core/_class.funcs.php (+0/-10)
qp_inc/_core/_misc.funcs.php (+5/-3)
qp_inc/_core/_param.funcs.php (+21/-8)
qp_inc/_core/model/__core.install.php (+32/-32)
qp_inc/_core/model/_pagecache.class.php (+119/-150)
qp_inc/_core/model/_timer.class.php (+52/-76)
qp_inc/_core/model/dataobjects/_dataobject.class.php (+250/-233)
qp_inc/_core/model/dataobjects/_dataobjectcache.class.php (+140/-174)
qp_inc/_core/model/dataobjects/_dataobjectlist.class.php (+43/-48)
qp_inc/_core/model/dataobjects/_dataobjectlist2.class.php (+64/-93)
qp_inc/_core/model/db/_db.class.php (+405/-379)
qp_inc/_core/model/db/_upgrade.funcs.php (+368/-333)
qp_inc/_core/ui/_menu.class.php (+96/-117)
qp_inc/_core/ui/_uiwidget.class.php (+9/-9)
qp_inc/_core/ui/forms/_form.class.php (+816/-738)
qp_inc/_core/ui/results/_results.class.php (+595/-583)
qp_inc/_core/ui/results/_resultsel.class.php (+274/-266)
qp_inc/_vars.inc.php (+50/-100)
qp_inc/antispam/views/_ban.form.php (+1/-1)
qp_inc/blogs/model/_blog.funcs.php (+4/-8)
qp_inc/blogs/views/_blog_list.view.php (+43/-38)
qp_inc/blogs/views/_blog_urls.form.php (+1/-1)
qp_inc/blogs/views/_blog_user_perm.form.php (+0/-5)
qp_inc/categories/views/_category.form.php (+1/-1)
qp_inc/categories/views/_category_list.view.php (+92/-84)
qp_inc/categories/views/_category_move.form.php (+1/-1)
qp_inc/comments/model/_comment.funcs.php (+95/-110)
qp_inc/comments/views/_comment.form.php (+1/-1)
qp_inc/cron/_cron.funcs.php (+30/-43)
qp_inc/cron/cronjobs.ctrl.php (+123/-165)
qp_inc/cron/jobs/_prune_hits_sessions.job.php (+8/-7)
qp_inc/cron/model/_cronjob.class.php (+49/-48)
qp_inc/cron/views/_cronjob.form.php (+23/-48)
qp_inc/cron/views/_cronjob.view.php (+43/-65)
qp_inc/cron/views/_cronjob_list.view.php (+72/-73)
qp_inc/dashboard/dashboard.ctrl.php (+1/-1)
qp_inc/files/model/_filecache.class.php (+36/-50)
qp_inc/files/model/_filelist.class.php (+260/-309)
qp_inc/files/model/_fileroot.class.php (+94/-114)
qp_inc/files/model/_filerootcache.class.php (+34/-55)
qp_inc/files/model/_filetype.class.php (+72/-70)
qp_inc/files/model/_filetypecache.class.php (+37/-58)
qp_inc/files/views/_file_browse.view.php (+307/-337)
qp_inc/files/views/_file_browse_set.form.php (+1/-1)
qp_inc/files/views/_file_copy_move.form.php (+30/-76)
qp_inc/files/views/_file_delete.form.php (+30/-66)
qp_inc/files/views/_file_download.form.php (+31/-55)
qp_inc/files/views/_file_edit.form.php (+21/-46)
qp_inc/files/views/_file_links.view.php (+101/-127)
qp_inc/files/views/_file_permissions.form.php (+85/-112)
qp_inc/files/views/_file_properties.form.php (+44/-60)
qp_inc/files/views/_file_rename.form.php (+26/-55)
qp_inc/files/views/_file_upload.view.php (+298/-357)
qp_inc/files/views/_filetype.form.php (+65/-100)
qp_inc/files/views/_filetype_list.view.php (+79/-103)
qp_inc/generic/model/_genericcache.class.php (+23/-38)
qp_inc/generic/model/_genericcategory.class.php (+27/-54)
qp_inc/generic/model/_genericcategorycache.class.php (+117/-137)
qp_inc/generic/model/_genericelement.class.php (+37/-72)
qp_inc/generic/model/_genericordered.class.php (+30/-61)
qp_inc/generic/model/_genericorderedcache.class.php (+26/-55)
qp_inc/generic/views/_generic_category.form.php (+24/-49)
qp_inc/generic/views/_generic_list.inc.php (+63/-82)
qp_inc/generic/views/_generic_ordered_list.inc.php (+69/-87)
qp_inc/items/item_statuses.ctrl.php (+1/-1)
qp_inc/items/items.ctrl.php (+13/-24)
qp_inc/items/model/_item.class.php (+5/-5)
qp_inc/items/model/_itemlight.class.php (+1/-1)
qp_inc/items/model/_link.class.php (+36/-45)
qp_inc/items/model/_linkcache.class.php (+36/-62)
qp_inc/items/views/_item_history.view.php (+32/-55)
qp_inc/items/views/_item_list_full.view.php (+182/-213)
qp_inc/items/views/_item_list_sidebar.view.php (+117/-152)
qp_inc/items/views/_item_list_table.view.php (+88/-96)
qp_inc/items/views/_item_list_track.view.php (+194/-201)
qp_inc/items/views/inc/_item_links.inc.php (+54/-83)
qp_inc/locales/_charset.funcs.php (+0/-1)
qp_inc/locales/_locale.funcs.php (+37/-29)
qp_inc/locales/locales.ctrl.php (+14/-17)
qp_inc/plugins/model/_plugins.class.php (+2/-2)
qp_inc/plugins/model/_plugins_admin.class.php (+14/-14)
qp_inc/plugins/model/_plugins_admin_no_db.class.php (+24/-35)
qp_inc/plugins/model/_pluginsettings.class.php (+16/-37)
qp_inc/plugins/model/_pluginusersettings.class.php (+35/-54)
qp_inc/plugins/plugins.ctrl.php (+745/-928)
qp_inc/plugins/views/_plugin_list.view.php (+161/-226)
qp_inc/plugins/views/_plugin_list_available.view.php (+34/-62)
qp_inc/plugins/views/_plugin_settings.form.php (+87/-143)
qp_inc/sessions/_sessions.init.php (+46/-71)
qp_inc/sessions/goals.ctrl.php (+140/-167)
qp_inc/sessions/model/_goal.class.php (+50/-43)
qp_inc/sessions/model/_hit.class.php (+2/-2)
qp_inc/sessions/model/_hitlist.class.php (+1/-1)
qp_inc/sessions/model/_hitlog.funcs.php (+15/-40)
qp_inc/sessions/model/_sessions.install.php (+32/-55)
qp_inc/sessions/views/_goal.form.php (+30/-40)
qp_inc/sessions/views/_goal_hitsummary.view.php (+47/-58)
qp_inc/sessions/views/_stats_browserhits.view.php (+57/-73)
qp_inc/sessions/views/_stats_direct.view.php (+48/-66)
qp_inc/sessions/views/_stats_goalhits.view.php (+139/-129)
qp_inc/sessions/views/_stats_goals.view.php (+74/-79)
qp_inc/sessions/views/_stats_hit_list.view.php (+128/-141)
qp_inc/sessions/views/_stats_refdomains.view.php (+88/-100)
qp_inc/sessions/views/_stats_refsearches.view.php (+71/-84)
qp_inc/sessions/views/_stats_robots.view.php (+80/-101)
qp_inc/sessions/views/_stats_search_keywords.view.php (+154/-147)
qp_inc/sessions/views/_stats_sessions.view.php (+34/-51)
qp_inc/sessions/views/_stats_sessions_list.view.php (+65/-80)
qp_inc/sessions/views/_stats_summary.view.php (+120/-140)
qp_inc/sessions/views/_stats_syndication.view.php (+38/-55)
qp_inc/sessions/views/_stats_useragents.view.php (+78/-93)
qp_inc/settings/model/_abstractsettings.class.php (+316/-357)
qp_inc/templates/model/_template.class.php (+11/-11)
qp_inc/templates/model/_templatecache.class.php (+2/-2)
qp_inc/templates/views/_template.form.php (+2/-2)
qp_inc/templates/views/_template_list_available.view.php (+1/-1)
qp_inc/templates/views/_template_list_installed.view.php (+4/-4)
qp_inc/templates/views/_template_select.view.php (+3/-3)
qp_inc/tools/tools.ctrl.php (+10/-6)
qp_inc/tools/views/_phpinfo.view.php (+7/-4)
qp_inc/tools/views/_system_list.view.php (+123/-194)
qp_inc/users/model/_group.class.php (+334/-288)
qp_inc/users/model/_user.class.php (+2/-2)
qp_inc/users/model/_user.funcs.php (+127/-113)
qp_inc/users/model/_usercache.class.php (+63/-83)
qp_inc/users/model/_usersettings.class.php (+58/-85)
qp_inc/users/views/_group.form.php (+114/-156)
qp_inc/users/views/_user.form.php (+1/-1)
qp_inc/users/views/_user_list.view.php (+186/-214)
qp_inc/widgets/_bloglist.widget.php (+19/-0)
qp_inc/widgets/_category_list.widget.php (+34/-7)
qp_inc/widgets/_comment_list.widget.php (+28/-2)
qp_inc/widgets/_common_links.widget.php (+22/-1)
qp_inc/widgets/_free_html.widget.php (+19/-0)
qp_inc/widgets/_item_list.widget.php (+47/-2)
qp_inc/widgets/_link_list.widget.php (+28/-3)
qp_inc/widgets/_linkblog.widget.php (+34/-3)
qp_inc/widgets/_logo.widget.php (+28/-2)
qp_inc/widgets/_longdesc.widget.php (+16/-0)
qp_inc/widgets/_media_index.widget.php (+52/-2)
qp_inc/widgets/_menu_link.widget.php (+39/-5)
qp_inc/widgets/_page_list.widget.php (+28/-3)
qp_inc/widgets/_post_list.widget.php (+28/-3)
qp_inc/widgets/_related_post_list.widget.php (+28/-3)
qp_inc/widgets/_search_form.widget.php (+19/-0)
qp_inc/widgets/_single_item.widget.php (+28/-3)
qp_inc/widgets/_tag_cloud.widget.php (+27/-2)
qp_inc/widgets/_tagline.widget.php (+18/-3)
qp_inc/widgets/_title.widget.php (+18/-2)
qp_inc/widgets/_user_tools.widget.php (+23/-0)
qp_inc/widgets/_xml_feeds.widget.php (+22/-0)
qp_inc/widgets/model/_widget.class.php (+3/-3)
qp_inc/widgets/model/_widgetcache.class.php (+2/-2)
qp_inc/widgets/views/_widget.form.php (+1/-1)
qp_inc/widgets/views/_widget_list.view.php (+24/-27)
qp_inc/widgets/widgets.ctrl.php (+6/-6)
qp_inc/xmlrpc/apis/_blogger.api.php (+166/-177)
qp_inc/xmlrpc/model/_xmlrpc.funcs.php (+11/-8)
qp_install/_functions_create.php (+29/-49)
qp_install/_functions_install.php (+32/-28)
qp_install/index.php (+5/-10)
qp_locales/de/_global.php (+2511/-0)
qp_locales/de/de-DE.locale.php (+27/-0)
qp_locales/en/en-AU.locale.php (+27/-0)
qp_locales/en/en-CA.locale.php (+27/-0)
qp_locales/en/en-GB.locale.php (+27/-0)
qp_locales/en/en-IL.locale.php (+27/-0)
qp_locales/en/en-NZ.locale.php (+27/-0)
qp_locales/en/en-SG.locale.php (+27/-0)
qp_locales/fr/_global.php (+2335/-0)
qp_locales/fr/fr-BE.locale.php (+27/-0)
qp_locales/fr/fr-CA.locale.php (+27/-0)
qp_locales/fr/fr-FR.locale.php (+27/-0)
qp_locales/php/de/_global.php (+0/-2507)
qp_locales/php/de/de-DE.locale.php (+0/-21)
qp_locales/php/en/en-AU.locale.php (+0/-21)
qp_locales/php/en/en-CA.locale.php (+0/-21)
qp_locales/php/en/en-GB.locale.php (+0/-21)
qp_locales/php/en/en-IL.locale.php (+0/-21)
qp_locales/php/en/en-NZ.locale.php (+0/-21)
qp_locales/php/en/en-SG.locale.php (+0/-21)
qp_locales/php/fr/_global.php (+0/-2331)
qp_locales/php/fr/fr-BE.locale.php (+0/-21)
qp_locales/php/fr/fr-CA.locale.php (+0/-21)
qp_locales/php/fr/fr-FR.locale.php (+0/-21)
qp_locales/php/ru/_global.php (+0/-2465)
qp_locales/php/ru/ru-RU.locale.php (+0/-21)
qp_locales/php/tr/_global.php (+0/-2137)
qp_locales/php/tr/tr-TR.locale.php (+0/-21)
qp_locales/ru/_global.php (+2469/-0)
qp_locales/ru/ru-RU.locale.php (+27/-0)
qp_locales/tr/_global.php (+2141/-0)
qp_locales/tr/tr-TR.locale.php (+27/-0)
qp_plugins/twitter_plugin/_twitter.plugin.php (+1/-1)
qp_rsc/js/communication.js (+2/-4)
qp_srvc/comment_post.php (+34/-45)
qp_srvc/cron_exec.php (+46/-39)
qp_srvc/login.php (+316/-317)
qp_srvc/track.php (+33/-40)
qp_view_admin/_access_denied.main.php (+10/-8)
qp_view_admin/_adminUI_general.class.php (+3/-3)
qp_view_admin/_html_footer.inc.php (+27/-46)
qp_view_admin/admin.global.css (+1/-1)
qp_view_admin/conf_error.main.php (+20/-26)
qp_view_admin/earth/_adminUI.class.php (+22/-33)
qp_view_admin/earth/style.css (+4/-76)
qp_view_admin/fire/_adminUI.class.php (+22/-33)
qp_view_admin/fire/style.css (+5/-86)
qp_view_admin/water/_adminUI.class.php (+22/-33)
qp_view_admin/water/style.css (+5/-77)
qp_view_admin/wind/_adminUI.class.php (+22/-33)
qp_view_admin/wind/style.css (+4/-75)
To merge this branch: bzr merge lp:~quam-plures-core/quam-plures/qp5_next_branch
Reviewer Review Type Date Requested Status
Quam Plures Core Team Pending
Review via email: mp+153917@code.launchpad.net

Description of the change

http://forums.quamplures.net/viewtopic.php?f=6&t=1896 ~200 files played with, almost all of which are "done" per the monster goal. works without issue :)

To post a comment you must log in.
7662. By EdB

found and fixed 2 fatal flaws :(

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'a_notemplate.php'
--- a_notemplate.php 2012-07-29 20:36:41 +0000
+++ a_notemplate.php 2013-03-20 18:13:29 +0000
@@ -51,7 +51,6 @@
51// --------------------- PAGE LEVEL CACHING SUPPORT ---------------------51// --------------------- PAGE LEVEL CACHING SUPPORT ---------------------
52// This is totally optional. General caching must be enabled52// This is totally optional. General caching must be enabled
53// in Global settings, otherwise this will do nothing.53// in Global settings, otherwise this will do nothing.
54load_class( '_core/model/_pagecache.class.php' );
55$PageCache = new PageCache( NULL );54$PageCache = new PageCache( NULL );
5655
57// Check for cached content & Start caching if needed:56// Check for cached content & Start caching if needed:
5857
=== modified file 'admin.php'
--- admin.php 2011-01-09 17:19:59 +0000
+++ admin.php 2013-03-20 18:13:29 +0000
@@ -1,183 +1,131 @@
1<?php1<?php
2/**2/**
3 * This is the main dispatcher for the admin interface.3 * This is the main dispatcher for the admin interface
4 *4 *
5 * IF YOU ARE READING THIS IN YOUR WEB BROWSER, IT MEANS THAT PHP IS NOT PROPERLY INSTALLED5 * IF YOU ARE READING THIS IN YOUR WEB BROWSER, IT MEANS THAT PHP IS NOT PROPERLY
6 * ON YOUR WEB SERVER. IF YOU DON'T KNOW WHAT THIS MEANS, CONTACT YOUR SERVER ADMINISTRATOR6 * INSTALLED ON YOUR WEB SERVER. IF YOU DON'T KNOW WHAT THIS MEANS, CONTACT YOUR
7 * OR YOUR HOSTING COMPANY.7 * SERVER ADMINISTRATOR OR YOUR HOSTING COMPANY.
8 *8 *
9 * This file is part of Quam Plures - {@link http://quamplures.net/}9 * @todo (3048) EdB> this file is 1 of 2 that sets the default admin template (part of "Get the Admin template")
10 * See also {@link https://launchpad.net/quam-plures}.10 * @todo (1111) the "Redirect old-style URLs" check is probably obsolete
11 *11 * @author {@link http://wonderwinds.com/ Ed Bennett}
12 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}12 * @author {@link http://progidistri.com/ PROGIDISTRI}
13 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}13 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
14 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.14 * @author {@link http://fplanque.net/ Francois PLANQUE}
15 * Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.15 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
16 *16 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
17 * {@internal License choice17 * @package admin
18 * - If you have received this file as part of a package, please find the license.txt file in
19 * the same folder or the closest folder above for complete license terms.
20 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
21 * then you must choose one of the following licenses before using the file:
22 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
23 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
24 * }}
25 *
26 * {@internal Open Source relicensing agreement:
27 * Daniel HAHLER grants Francois PLANQUE the right to license
28 * Daniel HAHLER's contributions to this file and the b2evolution project
29 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
30 *
31 * PROGIDISTRI S.A.S. grants Francois PLANQUE the right to license
32 * PROGIDISTRI S.A.S.'s contributions to this file and the b2evolution project
33 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
34 * }}
35 *
36 * @package pond
37 */18 */
3819
39
40/**20/**
41 * Do the MAIN initializations:21 * Load the configuration minimum
42 */22 */
43require_once dirname(__FILE__).'/qp_config/_config.php';23require_once dirname(__FILE__).'/qp_config/_config.php';
4424
4525// Is this an admin page? Use is_admin_page() to query it because it may change
46/**
47 * @global boolean Is this an admin page? Use {@link is_admin_page()} to query it, because it may change.
48 */
49$is_admin_page = true;26$is_admin_page = true;
50
51
52$login_required = true;27$login_required = true;
28
29/**
30 * Main initialization, without a specific blog identified
31 */
53require_once $inc_path.'_main.inc.php';32require_once $inc_path.'_main.inc.php';
5433
5534// Check global permission
56// Check global permission:
57if( ! $current_User->check_perm( 'admin', 'any' ) )35if( ! $current_User->check_perm( 'admin', 'any' ) )
58{ // No permission to access admin...36{
37 // No permission to access admin...
59 require $admintemplates_path.'_access_denied.main.php';38 require $admintemplates_path.'_access_denied.main.php';
60}39}
6140
6241/**
63/*
64 * Asynchronous processing options that may be required on any page42 * Asynchronous processing options that may be required on any page
65 */43 */
66require_once $inc_path.'_async.inc.php';44require_once $inc_path.'_async.inc.php';
6745
6846// Get the blog from param, defaulting to the last selected one for this user:
69/*47// we need it for quite a few of the menu urls
70 * Get the blog from param, defaulting to the last selected one for this user:48$user_selected_blog = (int)$UserSettings->get( 'selected_blog' );
71 * we need it for quite a few of the menu urls
72 */
73$user_selected_blog = (int)$UserSettings->get('selected_blog');
74$BlogCache = & get_Cache( 'BlogCache' );49$BlogCache = & get_Cache( 'BlogCache' );
75if( param( 'blog', 'integer', NULL, true ) === NULL // We got no explicit blog choice (not even '0' for 'no blog'):50if( param( 'blog', 'integer', NULL, true ) === NULL // no explicit blog choice, not even '0' for 'no blog'
76 || ($blog > 0 && ! ($Blog = & $BlogCache->get_by_ID( $blog, false, false )) )) // or we requested a nonexistent blog51 || ( $blog > 0 && ! ( $Blog = & $BlogCache->get_by_ID( $blog, false, false ) ) ) ) // we requested a nonexistent blog
77{ // Try the memorized blog from the previous action:52{
53 // Try the memorized blog from the previous action
78 $blog = $user_selected_blog;54 $blog = $user_selected_blog;
79 if( ! ($Blog = & $BlogCache->get_by_ID( $blog, false, false ) ) )55 if( ! ( $Blog = & $BlogCache->get_by_ID( $blog, false, false ) ) )
80 { // That one doesn't exist either...56 {
57 // That one doesn't exist either...
81 $blog = 0;58 $blog = 0;
82 }59 }
83}60}
84elseif( $blog != $user_selected_blog )61elseif( $blog != $user_selected_blog )
85{ // We have selected a new & valid blog. Update UserSettings for selected blog:62{
63 // We have selected a new & valid blog. Update UserSettings for selected blog
86 set_working_blog( $blog );64 set_working_blog( $blog );
87}65}
8866
8967// bookmarklet, upload (upload actually means sth like: select img for post)
90// bookmarklet, upload (upload actually means sth like: select img for post):
91param( 'mode', 'string', '', true );68param( 'mode', 'string', '', true );
9269
9370// Get the Admin template
94/*
95 * Get the Admin template
96 * TODO: Allow setting through GET param (dropdown in backoffice), respecting a checkbox "Use different setting on each computer" (if cookie_state handling is ready)
97 */
98$admin_template = $UserSettings->get( 'admin_template' );71$admin_template = $UserSettings->get( 'admin_template' );
99$admin_template_path = $admintemplates_path.'%s/_adminUI.class.php';72$admin_template_path = $admintemplates_path.'%s/_adminUI.class.php';
10073
101if( ! $admin_template || ! file_exists( sprintf( $admin_template_path, $admin_template ) ) )74if( ! $admin_template || ! file_exists( sprintf( $admin_template_path, $admin_template ) ) )
102{ // there's no template for the user75{
103 if( !$admin_template )76 // there's no template for the user
104 {
105 $Debuglog->add( 'The user has no admin template set.', 'template' );
106 }
107 else
108 {
109 $Debuglog->add( 'The admin template ['.$admin_template.'] set by the user does not exist.', 'template' );
110 }
111
112 $admin_template = $Settings->get( 'default_admin_template' );77 $admin_template = $Settings->get( 'default_admin_template' );
11378
114 if( !$admin_template || !file_exists( sprintf( $admin_template_path, $admin_template ) ) )79 if( ! $admin_template || ! file_exists( sprintf( $admin_template_path, $admin_template ) ) )
115 { // even the default template does not exist!80 {
116 if( !$admin_template )81 // even the default template does not exist!
117 {82 // set 'wind' as the admin template if it exists
118 $Debuglog->add( 'There is no default admin template set!', 'template' );83 if( file_exists( sprintf( $admin_template_path, 'wind' ) ) )
119 }84 {
120 else
121 {
122 $Debuglog->add( 'The default admin template ['.$admin_template.'] does not exist!', array('template','error') );
123 }
124
125 if( file_exists(sprintf( $admin_template_path, 'wind' )) )
126 { // 'wind' - the official starting template - exist
127 $admin_template = 'wind';85 $admin_template = 'wind';
128
129 $Debuglog->add( 'Falling back to "wind" admin template.', 'template' );
130 }86 }
131 else87 else
132 { // get the first one available one88 {
89 // get the first one available one
133 $admin_template_dirs = get_admin_templates();90 $admin_template_dirs = get_admin_templates();
13491
135 if( $admin_template_dirs === false )92 if( $admin_template_dirs === false )
136 {93 {
137 $Debuglog->add( 'No admin template found! Check that the path '.$admintemplates_path.' exists.', array('template','error') );94 // debuglog->add removed
138 }95 }
139 elseif( empty($admin_template_dirs) )96 elseif( empty( $admin_template_dirs ) )
140 { // No admin template directories found97 {
141 $Debuglog->add( 'No admin template found! Check that there are templates in '.$admintemplates_path.'.', array('template','error') );98 // No admin template directories found
99 // debuglog->add removed
142 }100 }
143 else101 else
144 {102 {
145 $admin_template = array_shift($admin_template_dirs);103 $admin_template = array_shift( $admin_template_dirs );
146 $Debuglog->add( 'Falling back to first available template.', 'template' );
147 }104 }
148 }105 }
149 }106 }
150}107}
108
109// we die without an admin template
151if( ! $admin_template )110if( ! $admin_template )
152{111{
153 $Debuglog->display( 'No admin template available!', '', true, 'template' );112 $Debuglog->display( 'No admin template available!', '', true, 'template' );
154 die(1);113 die(1);
155}114}
156115
157$Debuglog->add( 'Using admin template &laquo;'.$admin_template.'&raquo;', 'template' );
158
159/**116/**
160 * Load the AdminUI class for the template.117 * Load the AdminUI class for the template
161 */118 */
162require_once $admintemplates_path.$admin_template.'/_adminUI.class.php';119require_once $admintemplates_path.$admin_template.'/_adminUI.class.php';
163/**120
164 * This is the Admin UI object which handles the UI for the backoffice.121// This is the Admin UI object which handles the UI for the backoffice
165 *
166 * @global AdminUI
167 */
168$AdminUI = new AdminUI();122$AdminUI = new AdminUI();
169123
170124// Pass over to controller ... get requested controller and memorize it
171/*
172 * Pass over to controller...
173 */
174
175// Get requested controller and memorize it:
176param( 'ctrl', '/^[a-z0-9_]+$/', 'dashboard', true );125param( 'ctrl', '/^[a-z0-9_]+$/', 'dashboard', true );
177126
178127// Redirect old-style URLs (e.g. /admin/plugins.php), if they come here because the webserver
179// Redirect old-style URLs (e.g. /admin/plugins.php), if they come here because the webserver maps "/admin/" to "/admin.php"128// maps "/admin/" to "/admin.php" NOTE: this is just meant as a transformation from pre-1.8 to 1.8!
180// NOTE: this is just meant as a transformation from pre-1.8 to 1.8!
181if( ! empty( $_SERVER['PATH_INFO'] ) && $_SERVER['PATH_INFO'] != $_SERVER['PHP_SELF'] ) // the "!= PHP_SELF" check seems needed by IIS..129if( ! empty( $_SERVER['PATH_INFO'] ) && $_SERVER['PATH_INFO'] != $_SERVER['PHP_SELF'] ) // the "!= PHP_SELF" check seems needed by IIS..
182{130{
183 // Try to find the appropriate controller (ctrl) setting131 // Try to find the appropriate controller (ctrl) setting
@@ -196,7 +144,7 @@
196 $query_string = explode( '&', $_SERVER['QUERY_STRING'] );144 $query_string = explode( '&', $_SERVER['QUERY_STRING'] );
197 foreach( $query_string as $k => $v )145 foreach( $query_string as $k => $v )
198 {146 {
199 $query_string[$k] = strip_tags($v);147 $query_string[$k] = strip_tags( $v );
200 }148 }
201 $query_string = '&'.implode( '&', $query_string );149 $query_string = '&'.implode( '&', $query_string );
202 }150 }
@@ -209,14 +157,15 @@
209 exit(0);157 exit(0);
210}158}
211159
212160// Check matching controller file
213// Check matching controller file:161if( ! isset( $ctrl_mappings[$ctrl] ) )
214if( !isset($ctrl_mappings[$ctrl]) )
215{162{
216 debug_die( 'The requested controller ['.$ctrl.'] does not exist.' );163 debug_die( 'The requested controller ['.$ctrl.'] does not exist.' );
217}164}
218165
219// Call the requested controller:166/**
167 * Call the requested controller
168 */
220require $inc_path.$ctrl_mappings[$ctrl];169require $inc_path.$ctrl_mappings[$ctrl];
221170
222?>171?>
223172
=== modified file 'qp_config/_advanced.php'
--- qp_config/_advanced.php 2011-09-05 06:55:25 +0000
+++ qp_config/_advanced.php 2013-03-20 18:13:29 +0000
@@ -515,7 +515,7 @@
515/**515/**
516 * File extensions that the admin will not be able to enable in the Settings516 * File extensions that the admin will not be able to enable in the Settings
517 */517 */
518$force_upload_forbiddenext = array( 'cgi', 'exe', 'htaccess', 'htpasswd', 'php', 'php3', 'php4', 'php5', 'php6', 'phtml', 'pl', 'vbs' );518$forbidden_upload_exts = array( 'cgi', 'exe', 'htaccess', 'htpasswd', 'php', 'php3', 'php4', 'php5', 'php6', 'phtml', 'pl', 'vbs' );
519519
520/**520/**
521 * Admin can configure max file upload size, but he won't be able to set it higher than this "max max" value.521 * Admin can configure max file upload size, but he won't be able to set it higher than this "max max" value.
522522
=== modified file 'qp_config/_locales.php'
--- qp_config/_locales.php 2013-02-28 16:40:18 +0000
+++ qp_config/_locales.php 2013-03-20 18:13:29 +0000
@@ -88,7 +88,7 @@
88 * - 'datefmt' : The date format for this language. See {@link date_i18n()}.88 * - 'datefmt' : The date format for this language. See {@link date_i18n()}.
89 * - 'timefmt' : The time format for this language. See {@link date_i18n()}.89 * - 'timefmt' : The time format for this language. See {@link date_i18n()}.
90 * - 'startofweek': Start of week for this locale. 0 means Sunday, 1 Monday etc.90 * - 'startofweek': Start of week for this locale. 0 means Sunday, 1 Monday etc.
91 * - 'messages' : The locale's directory name (contains php/_global.php; ONLY USED HERE).91 * - 'messages' : The locale's directory name (contains _global.php; ONLY USED HERE).
92 * - 'enabled' : Is the locale visible to the user (ONLY USED HERE)?92 * - 'enabled' : Is the locale visible to the user (ONLY USED HERE)?
93 */93 */
94$locales['en-US'] = array(94$locales['en-US'] = array(
9595
=== removed file 'qp_config/_upgrade.php'
--- qp_config/_upgrade.php 2010-12-31 12:12:03 +0000
+++ qp_config/_upgrade.php 1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
1<?php
2/**
3 * This file includes upgrade settings for Quam Plures.
4 *
5 * Quam Plures - {@link http://quamplures.net/}
6 * Released under GNU GPL License - {@link http://quamplures.net/license.html}
7 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
8 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
9 *
10 * @package pond
11 */
12if( !defined('QP_CONFIG_LOADED') ) die( 'Please, do not access this page directly.' );
13
14
15/**#@+
16 * Old b2 tables used exclusively by the cafelog upgrade mode of the install script.
17 *
18 * @global string
19 */
20$oldtableposts = 'b2posts';
21$oldtableusers = 'b2users';
22$oldtablesettings = 'b2settings';
23$oldtablecategories = 'b2categories';
24$oldtablecomments = 'b2comments';
25/**#@-*/
26
27
28?>
290
=== modified file 'qp_inc/_application.php'
--- qp_inc/_application.php 2013-03-12 06:26:03 +0000
+++ qp_inc/_application.php 2013-03-20 18:13:29 +0000
@@ -30,7 +30,7 @@
30$app_date = '2013-03-21';30$app_date = '2013-03-21';
3131
32// Displayed on the login screen32// Displayed on the login screen
33$app_banner = '<a href="'.$app_homepage.'"><img src="'.$rsc_url.'img/qp-logo.jpg" width="337" height="76" alt="'.$app_name.'" /></a>';33$app_banner = '<a href="'.$app_homepage.'"><img src="'.$rsc_url.'logo.jpg" width="337" height="76" alt="'.$app_name.'" /></a>';
3434
35// Displayed on admin pages (footer)35// Displayed on admin pages (footer)
36$app_footer_text = '<a href="'.$app_homepage.'" title="'.sprintf( T_('visit %s\' website'), $app_name ).'"><strong>'.$app_name.' v'.$app_version.'</strong></a>'36$app_footer_text = '<a href="'.$app_homepage.'" title="'.sprintf( T_('visit %s\' website'), $app_name ).'"><strong>'.$app_name.' v'.$app_version.'</strong></a>'
3737
=== modified file 'qp_inc/_core/__core.init.php'
--- qp_inc/_core/__core.init.php 2013-03-13 02:35:35 +0000
+++ qp_inc/_core/__core.init.php 2013-03-20 18:13:29 +0000
@@ -30,33 +30,47 @@
30 'T_antispam' => $app_db_tableprefix.'antispam',30 'T_antispam' => $app_db_tableprefix.'antispam',
31 'T_blogs' => $app_db_tableprefix.'blogs',31 'T_blogs' => $app_db_tableprefix.'blogs',
32 'T_categories' => $app_db_tableprefix.'categories',32 'T_categories' => $app_db_tableprefix.'categories',
33 'T_coll_group_perms' => $app_db_tableprefix.'bloggroups',33 'T_blog_groups' => $app_db_tableprefix.'bloggroups', // new
34 'T_coll_user_perms' => $app_db_tableprefix.'blogusers',34 'T_coll_group_perms' => $app_db_tableprefix.'bloggroups', // old, going away
35 'T_blog_users' => $app_db_tableprefix.'blogusers', // new
36 'T_coll_user_perms' => $app_db_tableprefix.'blogusers', // old, going away
35 'T_comments' => $app_db_tableprefix.'comments',37 'T_comments' => $app_db_tableprefix.'comments',
36 'T_cron__log' => $app_db_tableprefix.'cron__log',38 'T_cron_log' => $app_db_tableprefix.'cron__log', // new
37 'T_cron__task' => $app_db_tableprefix.'cron__task',39 'T_cron__log' => $app_db_tableprefix.'cron__log', // old, going away
40 'T_cron_task' => $app_db_tableprefix.'cron__task', // new
41 'T_cron__task' => $app_db_tableprefix.'cron__task', // old, going away
38 'T_files' => $app_db_tableprefix.'files',42 'T_files' => $app_db_tableprefix.'files',
39 'T_filetypes' => $app_db_tableprefix.'filetypes',43 'T_filetypes' => $app_db_tableprefix.'filetypes',
40 'T_groups' => $app_db_tableprefix.'groups',44 'T_groups' => $app_db_tableprefix.'groups',
41 'T_global__cache' => $app_db_tableprefix.'global__cache',45 'T_global__cache' => $app_db_tableprefix.'global__cache',
42 'T_items__prerendering' => $app_db_tableprefix.'items__prerendering',46 'T_item_prerendering' => $app_db_tableprefix.'items__prerendering', // new
43 'T_items__status' => $app_db_tableprefix.'items__status',47 'T_items__prerendering' => $app_db_tableprefix.'items__prerendering', // old, going away
44 'T_items__version' => $app_db_tableprefix.'items__version',48 'T_item_status' => $app_db_tableprefix.'items__status', // new
49 'T_items__status' => $app_db_tableprefix.'items__status', // old, going away
50 'T_item_versions' => $app_db_tableprefix.'items__version', // new
51 'T_items__version' => $app_db_tableprefix.'items__version', // old, going away
45 'T_links' => $app_db_tableprefix.'links',52 'T_links' => $app_db_tableprefix.'links',
46 'T_locales' => $app_db_tableprefix.'locales',53 'T_locales' => $app_db_tableprefix.'locales',
47 'T_plugins' => $app_db_tableprefix.'plugins',54 'T_plugins' => $app_db_tableprefix.'plugins',
48 'T_pluginevents' => $app_db_tableprefix.'pluginevents',55 'T_plugin_events' => $app_db_tableprefix.'pluginevents', // new
49 'T_pluginsettings' => $app_db_tableprefix.'pluginsettings',56 'T_pluginevents' => $app_db_tableprefix.'pluginevents', // old, going away
50 'T_pluginusersettings' => $app_db_tableprefix.'pluginusersettings',57 'T_plugin_settings' => $app_db_tableprefix.'pluginsettings', // new
58 'T_pluginsettings' => $app_db_tableprefix.'pluginsettings', // old, going away
59 'T_plugin_usersettings' => $app_db_tableprefix.'pluginusersettings', // new
60 'T_pluginusersettings' => $app_db_tableprefix.'pluginusersettings', // old, going away
51 'T_settings' => $app_db_tableprefix.'settings',61 'T_settings' => $app_db_tableprefix.'settings',
52 'T_templates__container' => $app_db_tableprefix.'templates__container',62 'T_template_containers' => $app_db_tableprefix.'templates__container', // new
53 'T_templates__template' => $app_db_tableprefix.'templates__template',63 'T_templates__container' => $app_db_tableprefix.'templates__container', // old, going away
64 'T_templates' => $app_db_tableprefix.'templates__template', // new
65 'T_templates__template' => $app_db_tableprefix.'templates__template', // old, going away
54 'T_subscriptions' => $app_db_tableprefix.'subscriptions',66 'T_subscriptions' => $app_db_tableprefix.'subscriptions',
55 'T_users' => $app_db_tableprefix.'users',67 'T_users' => $app_db_tableprefix.'users',
56 'T_plugin_sharedfields' => $app_db_tableprefix.'plugin_sharedfields',68 'T_plugin_sharedfields' => $app_db_tableprefix.'plugin_sharedfields',
57 'T_plugin_sharedvalues' => $app_db_tableprefix.'plugin_sharedvalues',69 'T_plugin_sharedvalues' => $app_db_tableprefix.'plugin_sharedvalues',
58 'T_usersettings' => $app_db_tableprefix.'usersettings',70 'T_user_settings' => $app_db_tableprefix.'usersettings', // new
59 'T_widget' => $app_db_tableprefix.'widget',71 'T_usersettings' => $app_db_tableprefix.'usersettings', // old, going away
72 'T_widgets' => $app_db_tableprefix.'widget', // new
73 'T_widget' => $app_db_tableprefix.'widget', // old, going away
60 // old ones that leave after monster branch is done74 // old ones that leave after monster branch is done
61 'T_blog_settings' => $app_db_tableprefix.'coll_settings',75 'T_blog_settings' => $app_db_tableprefix.'coll_settings',
62 'T_coll_settings' => $app_db_tableprefix.'coll_settings', // old76 'T_coll_settings' => $app_db_tableprefix.'coll_settings', // old
@@ -100,10 +114,11 @@
100 'users' => 'users/users.ctrl.php',114 'users' => 'users/users.ctrl.php',
101 'upload' => 'files/upload.ctrl.php',115 'upload' => 'files/upload.ctrl.php',
102 'widgets' => 'widgets/widgets.ctrl.php',116 'widgets' => 'widgets/widgets.ctrl.php',
103 );117);
104118
105/**119/**
106 * _core_Module class120 * _core_Module class
121 *
107 * @package core122 * @package core
108 */123 */
109class _core_Module124class _core_Module
@@ -229,10 +244,6 @@
229 'text' => T_('Intros').'&hellip;',244 'text' => T_('Intros').'&hellip;',
230 'href' => $items_url.'tab=intros',245 'href' => $items_url.'tab=intros',
231 ),246 ),
232 'item_podcasts' => array(
233 'text' => T_('Podcasts').'&hellip;',
234 'href' => $items_url.'tab=podcasts',
235 ),
236 'item_links' => array(247 'item_links' => array(
237 'text' => T_('Sidebar links').'&hellip;',248 'text' => T_('Sidebar links').'&hellip;',
238 'href' => $items_url.'tab=links',249 'href' => $items_url.'tab=links',
239250
=== modified file 'qp_inc/_core/_class.funcs.php'
--- qp_inc/_core/_class.funcs.php 2013-03-12 21:17:25 +0000
+++ qp_inc/_core/_class.funcs.php 2013-03-20 18:13:29 +0000
@@ -138,14 +138,4 @@
138 }138 }
139}139}
140140
141/**
142 * Load class file. No-op for PHP5, uses __autoload().
143 *
144 * @deprecated - after "monster" all the load_class() calls will be removed
145 */
146function load_class( $class_path )
147{
148 return true;
149}
150
151?>141?>
152142
=== modified file 'qp_inc/_core/_misc.funcs.php'
--- qp_inc/_core/_misc.funcs.php 2013-03-12 21:17:25 +0000
+++ qp_inc/_core/_misc.funcs.php 2013-03-20 18:13:29 +0000
@@ -83,7 +83,7 @@
83 return $FiletypeCache;83 return $FiletypeCache;
8484
85 case 'GoalCache';85 case 'GoalCache';
86 $GoalCache = new DataObjectCache( 'Goal', false, 'T_track__goal', 'goal_', 'goal_ID', 'goal_name', 'goal_name' ); // COPY (FUNC)86 $GoalCache = new DataObjectCache( 'Goal', false, 'T_goals', 'goal_', 'goal_ID', 'goal_name', 'goal_name' ); // COPY (FUNC)
87 return $GoalCache;87 return $GoalCache;
8888
89 case 'GroupCache':89 case 'GroupCache':
@@ -111,7 +111,7 @@
111 return $ItemCatsCache;111 return $ItemCatsCache;
112112
113 case 'ItemStatusCache':113 case 'ItemStatusCache':
114 $Plugins->get_object_from_cacheplugin_or_create( 'ItemStatusCache', 'new GenericCache( \'GenericElement\', true, \'T_items__status\', \'pst_\', \'pst_ID\', NULL, \'\', T_(\'No status\') )' );114 $Plugins->get_object_from_cacheplugin_or_create( 'ItemStatusCache', 'new GenericCache( \'GenericElement\', true, \'T_item_status\', \'pst_\', \'pst_ID\', NULL, \'\', T_(\'No status\') )' );
115 return $ItemStatusCache;115 return $ItemStatusCache;
116116
117 case 'ItemTypeCache':117 case 'ItemTypeCache':
@@ -1134,7 +1134,7 @@
1134 * @param string Format to use ('simple', 'rfc')1134 * @param string Format to use ('simple', 'rfc')
1135 * - 'simple': Single email address.1135 * - 'simple': Single email address.
1136 * - 'rfc': Full email address, may include name (RFC2822) like example@example.org1136 * - 'rfc': Full email address, may include name (RFC2822) like example@example.org
1137 * or Me <example@example.org> or "Me" <example@example.org>1137 * or Me <example@example.org> or "Me" <example@example.org>
1138 *1138 *
1139 * @see Plugin::IsValidRawEmail()1139 * @see Plugin::IsValidRawEmail()
1140 * @see Plugin::IsValidFilteredEmail()1140 * @see Plugin::IsValidFilteredEmail()
@@ -3170,6 +3170,8 @@
3170 global $app_shortname;3170 global $app_shortname;
3171 global $app_version;3171 global $app_version;
31723172
3173 return '';
3174
3173 if( $Settings->get( 'webhelp_enabled' ) )3175 if( $Settings->get( 'webhelp_enabled' ) )
3174 {3176 {
3175 $manual_url = 'http://codex.quamplures.net/onlinehelp.php/'.$topic.'?lang='.$current_locale.'&amp;app='.$app_shortname.'&amp;version='.$app_version;3177 $manual_url = 'http://codex.quamplures.net/onlinehelp.php/'.$topic.'?lang='.$current_locale.'&amp;app='.$app_shortname.'&amp;version='.$app_version;
31763178
=== modified file 'qp_inc/_core/_param.funcs.php'
--- qp_inc/_core/_param.funcs.php 2013-03-12 21:17:25 +0000
+++ qp_inc/_core/_param.funcs.php 2013-03-20 18:13:29 +0000
@@ -38,9 +38,10 @@
38 * - '' (does nothing)38 * - '' (does nothing)
39 * - '/^...$/' check regexp pattern match (string)39 * - '/^...$/' check regexp pattern match (string)
40 * - boolean (will force type to boolean, but you can't use 'true' as a default40 * - boolean (will force type to boolean, but you can't use 'true' as a default
41 * since it has special meaning. There is no real reason to pass booleans on a41 * since it has special meaning. There is no real reason to pass booleans on a
42 * URL though. Passing 0 and 1 as integers seems to be best practice).42 * URL though. Passing 0 and 1 as integers seems to be best practice).
43 * Value type will be forced only if resulting value (probably from default then) is !== NULL43 * Value type will be forced only if resulting value (probably from default then)
44 * is !== NULL
44 * @param mixed Default value or TRUE if user input required45 * @param mixed Default value or TRUE if user input required
45 * @param boolean Do we need to memorize this to regenerate the URL for this page?46 * @param boolean Do we need to memorize this to regenerate the URL for this page?
46 * @param boolean Override if variable already set47 * @param boolean Override if variable already set
@@ -1622,7 +1623,7 @@
1622/**1623/**
1623 * Checks for sanitized code1624 * Checks for sanitized code
1624 *1625 *
1625 * WARNING: this does *NOT* (necessarilly) make the HTML code safe. It only checks1626 * WARNING: this does *NOT* (necessarily) make the HTML code safe. It only checks
1626 * on it and produces error messages. It is NOT (necessarily) safe to use the output.1627 * on it and produces error messages. It is NOT (necessarily) safe to use the output.
1627 *1628 *
1628 * @param string param name1629 * @param string param name
@@ -1743,8 +1744,9 @@
1743 $allow_javascript = false;1744 $allow_javascript = false;
1744 $allow_iframes = false;1745 $allow_iframes = false;
1745 $allow_objects = false;1746 $allow_objects = false;
1746 // fp> I don't know if it makes sense to bypass antispam in commenting context if the user1747 // fp> I don't know if it makes sense to bypass antispam in commenting context
1747 // has that kind of permissions. If so, then we also need to bypass in several other places.1748 // if the user has that kind of permissions. If so, then we also need to bypass
1749 // in several other places.
1748 $bypass_antispam = false;1750 $bypass_antispam = false;
1749 break;1751 break;
17501752
@@ -1825,7 +1827,9 @@
1825 {1827 {
1826 // We want to validate XHTML1828 // We want to validate XHTML
18271829
1828 // figure out what we want to validate against1830 // figure out what we want to validate against. $skip lets us bypass checks
1831 // when they don't matter, $flavor lets us validate against xhtml or html5
1832 // (eventually!), and $source gives us info about where we are checking from
1829 $skip = false;1833 $skip = false;
1830 $flavor = 'xhtml';1834 $flavor = 'xhtml';
1831 $source = array_merge( array(1835 $source = array_merge( array(
@@ -1839,7 +1843,16 @@
1839 $skip = true;1843 $skip = true;
1840 }1844 }
18411845
1842 // if we come from param_check_html() we're almost done1846 // we can skip if we're just changing locales on a user. $flavor will be xhtml
1847 // because we're in admin and admin doesn't do or need html5 stuff
1848 if( array_key_exists( 'userupdate', $_POST['actionArray'] )
1849 && array_key_exists( 'ctrl', $_POST ) )
1850 {
1851 $flavor = 'xhtml';
1852 $skip = true;
1853 }
1854
1855 // if we come from param_check_html() (but not on a user update) we're almost done
1843 if( ! $skip && $source['param_check_html'] )1856 if( ! $skip && $source['param_check_html'] )
1844 {1857 {
1845 global $Blog;1858 global $Blog;
18461859
=== modified file 'qp_inc/_core/model/__core.install.php'
--- qp_inc/_core/model/__core.install.php 2013-03-13 02:35:35 +0000
+++ qp_inc/_core/model/__core.install.php 2013-03-20 18:13:29 +0000
@@ -2,8 +2,9 @@
2/**2/**
3 * This is the install file for the core modules3 * This is the install file for the core modules
4 *4 *
5 * This gets updated through {@link db_delta()} which generates the queries needed5 * $schema_queries gets updated through {@link db_delta()} which generates the
6 * to get to this scheme. Please see {@link db_delta()} for things to take care of.6 * queries needed to get to this scheme. Please see {@link db_delta()} for things
7 * to take care of.
7 *8 *
8 * @author {@link http://wonderwinds.com/ Ed Bennett}9 * @author {@link http://wonderwinds.com/ Ed Bennett}
9 * @author {@link http://fplanque.net/ Francois PLANQUE}10 * @author {@link http://fplanque.net/ Francois PLANQUE}
@@ -15,9 +16,8 @@
1516
16global $db_storage_charset;17global $db_storage_charset;
1718
18// This gets updated through db_delta() which generates the queries needed to get to this scheme
19$schema_queries = array(19$schema_queries = array(
20 'T_antispam' => array( 'Creating table for Antispam Blacklist',20 'T_antispam' => array( 'Creating table for antispam',
21 "CREATE TABLE T_antispam (21 "CREATE TABLE T_antispam (
22 aspm_ID bigint(11) NOT NULL auto_increment,22 aspm_ID bigint(11) NOT NULL auto_increment,
23 aspm_string VARCHAR(80) NOT NULL,23 aspm_string VARCHAR(80) NOT NULL,
@@ -65,8 +65,8 @@
65 UNIQUE KEY blog_urlname (blog_urlname)65 UNIQUE KEY blog_urlname (blog_urlname)
66 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),66 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
6767
68 'T_coll_group_perms' => array( 'Creating blog-group permissions table',68 'T_blog_groups' => array( 'Creating blog-group permissions table',
69 "CREATE TABLE T_coll_group_perms (69 "CREATE TABLE T_blog_groups (
70 bloggroup_blog_ID INT(11) unsigned NOT NULL default 0,70 bloggroup_blog_ID INT(11) unsigned NOT NULL default 0,
71 bloggroup_group_ID INT(11) unsigned NOT NULL default 0,71 bloggroup_group_ID INT(11) unsigned NOT NULL default 0,
72 bloggroup_ismember TINYINT NOT NULL default 0,72 bloggroup_ismember TINYINT NOT NULL default 0,
@@ -91,8 +91,8 @@
91 PRIMARY KEY ( cset_blog_ID, cset_name )91 PRIMARY KEY ( cset_blog_ID, cset_name )
92 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),92 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
9393
94 'T_coll_user_perms' => array( 'Creating blog-user permissions table',94 'T_blog_users' => array( 'Creating blog-user permissions table',
95 "CREATE TABLE T_coll_user_perms (95 "CREATE TABLE T_blog_users (
96 bloguser_blog_ID INT(11) unsigned NOT NULL default 0,96 bloguser_blog_ID INT(11) unsigned NOT NULL default 0,
97 bloguser_user_ID INT(11) unsigned NOT NULL default 0,97 bloguser_user_ID INT(11) unsigned NOT NULL default 0,
98 bloguser_ismember TINYINT NOT NULL default 0,98 bloguser_ismember TINYINT NOT NULL default 0,
@@ -150,8 +150,8 @@
150 KEY comment_type (comment_type)150 KEY comment_type (comment_type)
151 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),151 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
152152
153 'T_cron__log' => array( 'Creating cron log table',153 'T_cron_log' => array( 'Creating cron log table',
154 "CREATE TABLE T_cron__log(154 "CREATE TABLE T_cron_log(
155 clog_ctsk_ID INT(10) unsigned not null,155 clog_ctsk_ID INT(10) unsigned not null,
156 clog_realstart_datetime DATETIME not null DEFAULT '2000-01-01 00:00:00',156 clog_realstart_datetime DATETIME not null DEFAULT '2000-01-01 00:00:00',
157 clog_realstop_datetime DATETIME,157 clog_realstop_datetime DATETIME,
@@ -160,8 +160,8 @@
160 PRIMARY KEY ( clog_ctsk_ID )160 PRIMARY KEY ( clog_ctsk_ID )
161 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),161 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
162162
163 'T_cron__task' => array( 'Creating cron tasks table',163 'T_cron_task' => array( 'Creating cron tasks table',
164 "CREATE TABLE T_cron__task(164 "CREATE TABLE T_cron_task(
165 ctsk_ID INT(10) unsigned not null AUTO_INCREMENT,165 ctsk_ID INT(10) unsigned not null AUTO_INCREMENT,
166 ctsk_start_datetime DATETIME not null DEFAULT '2000-01-01 00:00:00',166 ctsk_start_datetime DATETIME not null DEFAULT '2000-01-01 00:00:00',
167 ctsk_repeat_after INT(10) unsigned,167 ctsk_repeat_after INT(10) unsigned,
@@ -275,8 +275,8 @@
275 UNIQUE catpost ( postcat_cat_ID, postcat_post_ID )275 UNIQUE catpost ( postcat_cat_ID, postcat_post_ID )
276 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),276 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
277277
278 'T_items__prerendering' => array( 'Creating item prerendering table',278 'T_item_prerendering' => array( 'Creating item prerendering table',
279 "CREATE TABLE T_items__prerendering(279 "CREATE TABLE T_item_prerendering(
280 itpr_itm_ID INT(11) UNSIGNED NOT NULL,280 itpr_itm_ID INT(11) UNSIGNED NOT NULL,
281 itpr_format ENUM('htmlbody','entityencoded','xml','text') NOT NULL,281 itpr_format ENUM('htmlbody','entityencoded','xml','text') NOT NULL,
282 itpr_renderers TEXT NOT NULL,282 itpr_renderers TEXT NOT NULL,
@@ -285,8 +285,8 @@
285 PRIMARY KEY ( itpr_itm_ID, itpr_format )285 PRIMARY KEY ( itpr_itm_ID, itpr_format )
286 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),286 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
287287
288 'T_items__status' => array( 'Creating item statuses table',288 'T_item_status' => array( 'Creating item statuses table',
289 "CREATE TABLE T_items__status (289 "CREATE TABLE T_item_status (
290 pst_ID INT(11) unsigned not null AUTO_INCREMENT,290 pst_ID INT(11) unsigned not null AUTO_INCREMENT,
291 pst_name VARCHAR(30) not null,291 pst_name VARCHAR(30) not null,
292 PRIMARY KEY ( pst_ID )292 PRIMARY KEY ( pst_ID )
@@ -307,8 +307,8 @@
307 PRIMARY KEY ( ptyp_ID )307 PRIMARY KEY ( ptyp_ID )
308 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),308 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
309309
310 'T_items__version' => array( 'Creating item versions table',310 'T_item_versions' => array( 'Creating item versions table',
311 "CREATE TABLE T_items__version (311 "CREATE TABLE T_item_versions (
312 iver_itm_ID INT UNSIGNED NOT NULL,312 iver_itm_ID INT UNSIGNED NOT NULL,
313 iver_edit_user_ID INT UNSIGNED NULL,313 iver_edit_user_ID INT UNSIGNED NULL,
314 iver_edit_datetime DATETIME NOT NULL,314 iver_edit_datetime DATETIME NOT NULL,
@@ -369,24 +369,24 @@
369 INDEX plug_status( plug_status )369 INDEX plug_status( plug_status )
370 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),370 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
371371
372 'T_pluginevents' => array( 'Creating plugin events table',372 'T_plugin_events' => array( 'Creating plugin events table',
373 "CREATE TABLE T_pluginevents(373 "CREATE TABLE T_plugin_events(
374 pevt_plug_ID INT(11) UNSIGNED NOT NULL,374 pevt_plug_ID INT(11) UNSIGNED NOT NULL,
375 pevt_event VARCHAR(40) NOT NULL,375 pevt_event VARCHAR(40) NOT NULL,
376 pevt_enabled TINYINT NOT NULL DEFAULT 1,376 pevt_enabled TINYINT NOT NULL DEFAULT 1,
377 PRIMARY KEY ( pevt_plug_ID, pevt_event )377 PRIMARY KEY ( pevt_plug_ID, pevt_event )
378 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),378 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
379379
380 'T_pluginsettings' => array( 'Creating plugin settings table',380 'T_plugin_settings' => array( 'Creating plugin settings table',
381 "CREATE TABLE T_pluginsettings (381 "CREATE TABLE T_plugin_settings (
382 pset_plug_ID INT(11) UNSIGNED NOT NULL,382 pset_plug_ID INT(11) UNSIGNED NOT NULL,
383 pset_name VARCHAR(30) NOT NULL,383 pset_name VARCHAR(30) NOT NULL,
384 pset_value TEXT NULL,384 pset_value TEXT NULL,
385 PRIMARY KEY ( pset_plug_ID, pset_name )385 PRIMARY KEY ( pset_plug_ID, pset_name )
386 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),386 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
387387
388 'T_pluginusersettings' => array( 'Creating plugin user settings table',388 'T_plugin_usersettings' => array( 'Creating plugin user settings table',
389 "CREATE TABLE T_pluginusersettings (389 "CREATE TABLE T_plugin_usersettings (
390 puset_plug_ID INT(11) UNSIGNED NOT NULL,390 puset_plug_ID INT(11) UNSIGNED NOT NULL,
391 puset_user_ID INT(11) UNSIGNED NOT NULL,391 puset_user_ID INT(11) UNSIGNED NOT NULL,
392 puset_name VARCHAR(30) NOT NULL,392 puset_name VARCHAR(30) NOT NULL,
@@ -418,8 +418,8 @@
418 UNIQUE tag_name( tag_name )418 UNIQUE tag_name( tag_name )
419 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),419 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
420420
421 'T_templates__template' => array( 'Creating templates table',421 'T_templates' => array( 'Creating templates table',
422 "CREATE TABLE T_templates__template (422 "CREATE TABLE T_templates (
423 template_ID INT(10) unsigned NOT NULL auto_increment,423 template_ID INT(10) unsigned NOT NULL auto_increment,
424 template_name VARCHAR(32) NOT NULL,424 template_name VARCHAR(32) NOT NULL,
425 template_type ENUM('xhtml','html5','feed','other') NOT NULL default 'xhtml',425 template_type ENUM('xhtml','html5','feed','other') NOT NULL default 'xhtml',
@@ -429,8 +429,8 @@
429 KEY template_name( template_name )429 KEY template_name( template_name )
430 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),430 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
431431
432 'T_templates__container' => array( 'Creating template containers table',432 'T_template_containers' => array( 'Creating template containers table',
433 "CREATE TABLE T_templates__container (433 "CREATE TABLE T_template_containers (
434 sco_template_ID INT(10) unsigned NOT NULL,434 sco_template_ID INT(10) unsigned NOT NULL,
435 sco_name VARCHAR(40) NOT NULL,435 sco_name VARCHAR(40) NOT NULL,
436 sco_order TINYINT NOT NULL default 0,436 sco_order TINYINT NOT NULL default 0,
@@ -473,16 +473,16 @@
473 PRIMARY KEY ( cach_name )473 PRIMARY KEY ( cach_name )
474 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),474 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
475475
476 'T_usersettings' => array( 'Creating user settings table',476 'T_user_settings' => array( 'Creating user settings table',
477 "CREATE TABLE T_usersettings (477 "CREATE TABLE T_user_settings (
478 uset_user_ID INT(11) UNSIGNED NOT NULL,478 uset_user_ID INT(11) UNSIGNED NOT NULL,
479 uset_name VARCHAR(30) NOT NULL,479 uset_name VARCHAR(30) NOT NULL,
480 uset_value VARCHAR(255) NULL,480 uset_value VARCHAR(255) NULL,
481 PRIMARY KEY ( uset_user_ID, uset_name )481 PRIMARY KEY ( uset_user_ID, uset_name )
482 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),482 ) ENGINE = innodb DEFAULT CHARSET = $db_storage_charset" ),
483483
484 'T_widget' => array( 'Creating widgets table',484 'T_widgets' => array( 'Creating widgets table',
485 "CREATE TABLE T_widget (485 "CREATE TABLE T_widgets (
486 wi_ID INT(10) UNSIGNED auto_increment,486 wi_ID INT(10) UNSIGNED auto_increment,
487 wi_widget_blog_ID INT(11) UNSIGNED NOT NULL,487 wi_widget_blog_ID INT(11) UNSIGNED NOT NULL,
488 wi_sco_name VARCHAR(40) NOT NULL,488 wi_sco_name VARCHAR(40) NOT NULL,
489489
=== modified file 'qp_inc/_core/model/_pagecache.class.php'
--- qp_inc/_core/model/_pagecache.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/_pagecache.class.php 2013-03-20 18:13:29 +0000
@@ -1,72 +1,62 @@
1<?php1<?php
2/**2/**
3 * This file implements the PageCache class, which caches HTML pages genereated by the app.3 * This file implements the PageCache class
4 *4 *
5 * This file is part of Quam Plures - {@link http://quamplures.net/}5 * This caches HTML pages genereated by the app.
6 * See also {@link https://launchpad.net/quam-plures}.6 *
7 *7 * @todo (1111) vars type 'foo' need useful/valid descriptions
8 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}8 * @author {@link http://wonderwinds.com/ Ed Bennett}
9 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}9 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
10 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.10 * @author {@link http://fplanque.net/ Francois PLANQUE}
11 *11 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
12 * {@internal License choice12 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
13 * - If you have received this file as part of a package, please find the license.txt file in13 * @package core
14 * the same folder or the closest folder above for complete license terms.
15 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
16 * then you must choose one of the following licenses before using the file:
17 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
18 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
19 * }}
20 *
21 * {@internal Open Source relicensing agreement:
22 * }}
23 *
24 * @package pond
25 */14 */
26if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );15if(!defined('QP_MAIN_INIT')) die('fail');
27
2816
29/**17/**
30 * Page Cache.18 * PageCache class
31 *19 *
32 * @package pond20 * @package core
33 */21 */
34class PageCache22class PageCache
35{23{
36 /**24 /**
37 * How old can a cached object get before we consider it outdated25 * How old can a cached object get before we consider it outdated
26 * @var foo
38 */27 */
39 var $max_age_seconds = 300; // 5 minutes for now28 var $max_age_seconds = 300;
4029 /**
41 /**30 * After how many bytes should we output sth live while collecting cache content
42 * After how many bytes should we output sth live while collecting cache content:31 * @var foo
43 */32 */
44 var $output_chunk_size = 2000;33 var $output_chunk_size = 2000;
45
46 /**34 /**
47 * By default we consider caching not to be enabled35 * By default we consider caching not to be enabled
36 * @var foo
48 */37 */
49 var $is_enabled = false;38 var $is_enabled = false;
50
51 /**39 /**
52 *40 * FIX THIS
41 * @var foo
53 */42 */
54 var $ads_collcache_path;43 var $ads_collcache_path;
55
56 /**44 /**
57 * Filename of cache for current page45 * Filename of cache for current page
46 * @var foo
58 */47 */
59 var $cache_filepath;48 var $cache_filepath;
60 /**49 /**
61 * Progressively caching the content of the current page:50 * Progressively caching the content of the current page
51 * @var foo
62 */52 */
63 var $cached_page_content = '';53 var $cached_page_content = '';
64 /**54 /**
65 * Are we currently recording cache contents for this page?55 * Are we currently recording cache contents for this page?
56 * @var foo
66 */57 */
67 var $is_collecting = false;58 var $is_collecting = false;
6859
69
70 /**60 /**
71 * Constructor61 * Constructor
72 *62 *
@@ -74,17 +64,18 @@
74 */64 */
75 function PageCache( $Blog = NULL )65 function PageCache( $Blog = NULL )
76 {66 {
77 global $Debuglog;67 global $cache_path;
78 global $Settings;68 global $Settings;
79 global $cache_path;
8069
81 if( is_null($Blog) )70 if( is_null( $Blog ) )
82 { // Cache for "other" "genereic" "special" pages:71 {
72 // Cache for "other" "genereic" "special" pages
83 $this->ads_collcache_path = $cache_path.'general/';73 $this->ads_collcache_path = $cache_path.'general/';
8474
85 if( ! $Settings->get('general_cache_enabled') )75 if( ! $Settings->get( 'general_cache_enabled' ) )
86 { // We do NOT want caching for this collection76 {
87 $Debuglog->add( 'General cache not enabled.', 'cache' );77 // We do NOT want caching for this collection
78 // debuglog-add removed
88 }79 }
89 else80 else
90 {81 {
@@ -92,13 +83,15 @@
92 }83 }
93 }84 }
94 else85 else
95 { // Cache for a specific Blog/Collection:86 {
96 // We need to set this even if cache is not enabled (yet) bc it's used for creating:87 // Cache for a specific Blog/Collection
88 // We need to set this even if cache is not enabled (yet) bc it's used for creating
97 $this->ads_collcache_path = $cache_path.'c'.$Blog->ID.'/';89 $this->ads_collcache_path = $cache_path.'c'.$Blog->ID.'/';
9890
99 if( ! $Blog->get_setting('cache_enabled') )91 if( ! $Blog->get_setting( 'cache_enabled' ) )
100 { // We do NOT want caching for this collection92 {
101 $Debuglog->add( 'Cache not enabled for this blog.', 'cache' );93 // We do NOT want caching for this collection
94 // debuglog-add removed
102 }95 }
103 else96 else
104 {97 {
@@ -111,37 +104,35 @@
111 /**104 /**
112 * Get path to file for current URL105 * Get path to file for current URL
113 *106 *
114 * @todo fp> We may need to add some keys like the locale or the charset, I'm not sure.107 * @todo (0000) fp> We may need to add some keys like the locale or the charset, I'm not sure.
115 */108 */
116 function get_af_filecache_path()109 function get_af_filecache_path()
117 {110 {
118 global $Debuglog;111 global $ReqURI;
119 global $ReqHost, $ReqURI;112 global $ReqHost;
120113
121 // We want the cache for the current URL114 // We want the cache for the current URL
122 if( empty( $this->cache_filepath ) )115 if( empty( $this->cache_filepath ) )
123 {116 {
124 $ReqAbsUrl = $ReqHost.$ReqURI;117 $ReqAbsUrl = $ReqHost.$ReqURI;
125 $Debuglog->add( 'URL being cached: '.$ReqAbsUrl, 'cache' );118
126119 $this->cache_filepath = $this->gen_filecache_path( $ReqAbsUrl );
127 $this->cache_filepath = $this->gen_filecache_path( $ReqAbsUrl );
128
129 $Debuglog->add( 'Cache file: '.$this->cache_filepath, 'cache' );
130 }120 }
131121
132 return $this->cache_filepath;122 return $this->cache_filepath;
133 }123 }
134124
135125
136 /**126 /**
137 * Generate path for caching $url.127 * Generate path for caching $url
128 *
138 * @param string URL129 * @param string URL
139 * @return string130 * @return string
140 */131 */
141 function gen_filecache_path( $url )132 function gen_filecache_path( $url )
142 {133 {
143 $url_hash = md5($url); // fp> is this teh fastest way to hash this into something not too obvious to guess?134 // fp> is this the fastest way to hash this into something not too obvious to guess?
144135 $url_hash = md5( $url );
145 return $this->ads_collcache_path.$url_hash.'.page';136 return $this->ads_collcache_path.$url_hash.'.page';
146 }137 }
147138
@@ -153,29 +144,27 @@
153 */144 */
154 function invalidate( $url )145 function invalidate( $url )
155 {146 {
156 global $Debuglog;
157
158 $Debuglog->add( 'Invalidating:'.$url, 'cache' );
159
160 // What would be the cache file for the current URL?147 // What would be the cache file for the current URL?
161 $af_cache_file = $this->gen_filecache_path( $url );148 $af_cache_file = $this->gen_filecache_path( $url );
162
163 @unlink( $af_cache_file );149 @unlink( $af_cache_file );
164 }150 }
165151
166152
167 /**153 /**
154 * create cache
155 *
168 * @return boolean true if cache has been successfully created156 * @return boolean true if cache has been successfully created
169 */157 */
170 function cache_create()158 function cache_create()
171 {159 {
172 // Create by using the filemanager's default chmod. TODO> we may not want to make these publicly readable160 // Create by using the filemanager's default chmod.
161 // @todo (0000) we may not want to make these publicly readable
173 if( ! mkdir_r( $this->ads_collcache_path, NULL ) )162 if( ! mkdir_r( $this->ads_collcache_path, NULL ) )
174 {163 {
175 return false;164 return false;
176 }165 }
177166
178 // Clear contents of folder, if any:167 // Clear contents of folder, if any
179 cleardir_r( $this->ads_collcache_path );168 cleardir_r( $this->ads_collcache_path );
180169
181 return true;170 return true;
@@ -198,66 +187,57 @@
198 */187 */
199 function check()188 function check()
200 {189 {
201 global $Debuglog;
202 global $disp;190 global $disp;
203
204 global $Messages;191 global $Messages;
205192
206 if( ! $this->is_enabled )193 if( ! $this->is_enabled )
207 { // We do NOT want caching for this page194 {
208 $Debuglog->add( 'Cache not enabled. No lookup nor caching performed.', 'cache' );195 // We do NOT want caching for this page
209 return false;196 return false;
210 }197 }
211198
212 if( $disp == '404' )199 if( $disp == '404' )
213 { // We do NOT want caching for 404 pages (illimited possibilities!)200 {
214 $Debuglog->add( 'Never cache 404s!', 'cache' );201 // We do NOT want caching for 404 pages (illimited possibilities!)
215 return false;202 return false;
216 }203 }
217204
218 if( is_logged_in() )205 if( is_logged_in() )
219 { // We do NOT want caching when a user is logged in (private data)206 {
220 $Debuglog->add( 'Never cache pages for/from logged in members!', 'cache' );207 // We do NOT want caching when a user is logged in (private data)
221 return false;208 return false;
222 }209 }
223210
224 if( $Messages->count('all') )211 if( $Messages->count('all') )
225 { // There are some messages do be displayed. That means the user has done some action.212 {
213 // There are some messages do be displayed. That means the user has done some action.
226 // We do want to display those messages.214 // We do want to display those messages.
227 // There may also be more... like a "comment pending review" etc...215 // There may also be more... like a "comment pending review" etc...
228 // DO NOT CACHE and do not present a cached page.216 // DO NOT CACHE and do not present a cached page.
229 $Debuglog->add( 'Not caching because we have messages!', 'cache' );
230 return false;217 return false;
231 }218 }
232219
233 // TODO: fp> If the user has submitted a comment, we might actually want to invalidate the cache...
234
235
236 if( $this->retrieve() )220 if( $this->retrieve() )
237 { // We could retrieve:221 {
222 // We could retrieve
238 return true;223 return true;
239 }224 }
240225
241
242 $this->is_collecting = true;226 $this->is_collecting = true;
243
244 $Debuglog->add( 'Collecting started', 'cache' );
245
246 ob_start( array( & $this, 'output_handler'), $this->output_chunk_size );227 ob_start( array( & $this, 'output_handler'), $this->output_chunk_size );
247
248 return false;228 return false;
249 }229 }
250230
251231
252 /**232 /**
253 * Retrieve and output cache for current URL.233 * Retrieve and output cache for current URL
254 *234 *
255 * @return boolean true if we could retrieve235 * @return boolean true if we could retrieve
256 */236 */
257 function retrieve()237 function retrieve()
258 {238 {
259 global $Debuglog;239 global $ReqHost;
260 global $ReqHost, $ReqURI;240 global $ReqURI;
261 global $servertimenow;241 global $servertimenow;
262242
263 // What would be the cache file for the current URL?243 // What would be the cache file for the current URL?
@@ -275,48 +255,46 @@
275 */255 */
276256
277 $lines = @file( $af_cache_file, false );257 $lines = @file( $af_cache_file, false );
278 // fp> note we are using empty() so that we detect both the case where there is no file and the case wher ethe file258 // fp> note we are using empty() so that we detect both the case where there
279 // might have ended up empty because PHP crashed while writing to it or sth like that...259 // is no file and the case wher ethe file might have ended up empty because
280 if( ! empty($lines) )260 // PHP crashed while writing to it or sth like that...
281 { // We have data in the cache!261 if( ! empty( $lines ) )
282 $Debuglog->add( 'Retrieving from cache!', 'cache' );262 {
283263 // We have data in the cache!
284 // Check that the format of the file if OK.264 // Check that the format of the file if OK
285 $sep = trim($lines[2]);265 $sep = trim( $lines[2] );
286 unset($lines[2]);266 unset( $lines[2] );
287 if( $sep != '' )267 if( $sep != '' )
288 {268 {
289 $Debuglog->add( 'Cached file format not recognized, aborting retrieve.', 'cache' );
290 return false;269 return false;
291 }270 }
292271
293 // Retrieved cached URL:272 // Retrieved cached URL
294 $retrieved_url = trim($lines[0]);273 $retrieved_url = trim( $lines[0] );
295 unset($lines[0]);274 unset( $lines[0] );
296 if( $retrieved_url != $ReqHost.$ReqURI )275 if( $retrieved_url != $ReqHost.$ReqURI )
297 {276 {
298 $Debuglog->add( 'Cached file URL ['.$retrieved_url.'] does not match current URL, aborting retrieve.', 'cache' );
299 return false;277 return false;
300 }278 }
301279
302 // timestamp of cache generation:280 // timestamp of cache generation
303 $retrieved_ts = trim($lines[1]);281 $retrieved_ts = trim( $lines[1] );
304 unset($lines[1]);282 unset( $lines[1] );
305 $cache_age = $servertimenow-$retrieved_ts;283 $cache_age = $servertimenow-$retrieved_ts;
306 $Debuglog->add( 'Cache age: '.floor($cache_age/60).' min '.($cache_age % 60).' sec', 'cache' );
307 if( $cache_age > $this->max_age_seconds )284 if( $cache_age > $this->max_age_seconds )
308 { // Cache has expired285 {
286 // Cache has expired
309 return false;287 return false;
310 }288 }
311289
312 // Go through headers290 // Go through headers
313 $i = 2;291 $i = 2;
314 while( $headerline = trim($lines[++$i]) )292 while( $headerline = trim( $lines[++$i] ) )
315 {293 {
316 header( $headerline );294 header( $headerline );
317 unset($lines[$i]);295 unset( $lines[$i] );
318 }296 }
319 unset($lines[$i]);297 unset( $lines[$i] );
320298
321 // SEND CONTENT!299 // SEND CONTENT!
322 echo implode('',$lines);300 echo implode('',$lines);
@@ -326,7 +304,7 @@
326 }304 }
327305
328306
329 /**307 /**
330 * This is called every x bytes to provide real time output308 * This is called every x bytes to provide real time output
331 */309 */
332 function output_handler( $buffer )310 function output_handler( $buffer )
@@ -337,21 +315,17 @@
337315
338316
339 /**317 /**
340 * We are going to output personal data and we want to abort collecting the data for the cache.318 * We are going to output personal data and we want to abort collecting the data for the cache
341 */319 */
342 function abort_collect()320 function abort_collect()
343 {321 {
344 global $Debuglog;
345
346 if( ! $this->is_collecting )322 if( ! $this->is_collecting )
347 { // We are not collecting anyway323 {
324 // We are not collecting anyway
348 return;325 return;
349 }326 }
350327
351 $Debuglog->add( 'Aborting cache data collection...', 'cache' );
352
353 ob_end_flush();328 ob_end_flush();
354
355 // We are no longer collecting...329 // We are no longer collecting...
356 $this->is_collecting = false;330 $this->is_collecting = false;
357 }331 }
@@ -362,41 +336,42 @@
362 */336 */
363 function end_collect()337 function end_collect()
364 {338 {
365 global $Debuglog;
366
367 if( ! $this->is_collecting )339 if( ! $this->is_collecting )
368 { // We are not collecting340 {
341 // We are not collecting
369 return;342 return;
370 }343 }
371344
372 ob_end_flush();345 ob_end_flush();
373
374 // What would be the cache file for the current URL?346 // What would be the cache file for the current URL?
375 $af_cache_file = $this->get_af_filecache_path();347 $af_cache_file = $this->get_af_filecache_path();
376348
377 // fp> 'x' mode should either give an exclusive write lock or fail349 // fp> 'x' mode should either give an exclusive write lock or fail
378 // fp> TODO: this here should be ok, but it would be even better with locking the file when we start collecting cache350 // @todo (0000) fp> this here should be ok, but it would be even better with
351 // locking the file when we start collecting cache
379 if( ! $fh = @fopen( $af_cache_file.'.tmp', 'x', false ) )352 if( ! $fh = @fopen( $af_cache_file.'.tmp', 'x', false ) )
380 {353 {
381 $Debuglog->add( 'Could not open cache file!', 'cache' );354 // debuglog-add removed
382 }355 }
383 else356 else
384 {357 {
385 // Put the URL of the page we are caching into the cache. You can never be to paranoid!358 global $content_type_header;
386 // People can change their domain names, folder structures, etc... AND you cannot trust the hash to give a359 global $ReqHost;
387 // different file name in 100.00% of the cases! Serving a page for a different URL would be REEEEEALLLY BAAAAAAD!360 global $ReqURI;
388 global $ReqHost, $ReqURI;361 global $servertimenow;
362
363 // Put the URL of the page we are caching into the cache. You can never be
364 // to paranoid! People can change their domain names, folder structures, etc...
365 // AND you cannot trust the hash to give a different file name in 100.00% of
366 // the cases! Serving a page for a different URL would be REEEEEALLLY BAAAAAAD!
389 $file_head = $ReqHost.$ReqURI."\n";367 $file_head = $ReqHost.$ReqURI."\n";
390368
391 // Put the time of the page generation into the file (btw this is the time of when we started this script)369 // Put the time of the page generation into the file (btw this is the time of when we started this script)
392 global $servertimenow;
393 $file_head .= $servertimenow."\n";370 $file_head .= $servertimenow."\n";
394371 $file_head .= "\n";
395 $file_head .= "\n";
396372
397 // We need to write the content type!373 // We need to write the content type!
398 global $content_type_header;374 if( ! empty( $content_type_header ) )
399 if( !empty($content_type_header) )
400 {375 {
401 $file_head .= $content_type_header."\n";376 $file_head .= $content_type_header."\n";
402 }377 }
@@ -408,29 +383,23 @@
408383
409 // Now atomically replace old cache with new cache (at least on Linux)384 // Now atomically replace old cache with new cache (at least on Linux)
410 if( ! @rename( $af_cache_file.'.tmp', $af_cache_file ) )385 if( ! @rename( $af_cache_file.'.tmp', $af_cache_file ) )
411 { // Rename failed, we are probably on windows PHP <= 5.2.5... http://bugs.php.net/bug.php?id=44805386 {
387 // Rename failed, we are probably on windows PHP <= 5.2.5... http://bugs.php.net/bug.php?id=44805
412 // we have to split this:388 // we have to split this:
413 $Debuglog->add( 'Renaming of cache file failed. (Windows?)', 'cache' );389 // Kill cache
414 // Kill cache:
415 unlink( $af_cache_file );390 unlink( $af_cache_file );
416 // Now, some other process might start to try caching (and will likely give up since the .tmp file already exists)391 // Now, some other process might start to try caching (and will likely give
392 // up since the .tmp file already exists)
417 if( ! @rename( $af_cache_file.'.tmp', $af_cache_file ) )393 if( ! @rename( $af_cache_file.'.tmp', $af_cache_file ) )
418 { // Hide errors bc another PHP process could have beaten us to writing a new file there394 {
419 // Anyways, we still could not rename, let's drop the .tmp file:395 // Hide errors bc another PHP process could have beaten us to writing a new file there
396 // Anyways, we still could not rename, let's drop the .tmp file
420 unlink( $af_cache_file.'.tmp' );397 unlink( $af_cache_file.'.tmp' );
421 }398 }
422 else
423 {
424 $Debuglog->add( 'Cache updated... after unlink+rename!', 'cache' );
425 }
426 }
427 else
428 {
429 $Debuglog->add( 'Cache updated!', 'cache' );
430 }399 }
431 }400 }
432 }401 }
433402
434}403}
435404
436?>
437\ No newline at end of file405\ No newline at end of file
406?>
438407
=== modified file 'qp_inc/_core/model/_timer.class.php'
--- qp_inc/_core/model/_timer.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/_timer.class.php 2013-03-20 18:13:29 +0000
@@ -1,62 +1,43 @@
1<?php1<?php
2/**2/**
3 * This file implements the Timer class.3 * This file implements the Timer base class
4 *4 *
5 * This file is part of Quam Plures - {@link http://quamplures.net/}
6 * See also {@link https://launchpad.net/quam-plures}.
7 *
8 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
9 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
10 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
11 *
12 * {@internal License choice
13 * - If you have received this file as part of a package, please find the license.txt file in
14 * the same folder or the closest folder above for complete license terms.
15 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
16 * then you must choose one of the following licenses before using the file:
17 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
18 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
19 * }}
20 *
21 * {@internal Open Source relicensing agreement:
22 * Daniel HAHLER grants Francois PLANQUE the right to license
23 * Daniel HAHLER's contributions to this file and the b2evolution project
24 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
25 * }}
26 *
27 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
28 * @author fplanque: Francois PLANQUE.
29 * @author blueyed: Daniel HAHLER.
30 *
31 * @package pond
32 */
33if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
34
35/**
36 * This is a simple class to allow timing/profiling of code portions.5 * This is a simple class to allow timing/profiling of code portions.
37 *6 *
38 * @package pond7 * @todo (1111) vars type 'foo' need useful/valid descriptions
8 * @author {@link http://wonderwinds.com/ Ed Bennett}
9 * @author {@link http://fplanque.net/ Francois PLANQUE}
10 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
11 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
12 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
13 * @package core
14 */
15if(!defined('QP_MAIN_INIT')) die('fail');
16
17/**
18 * Timer base class
19 *
20 * @package core
39 */21 */
40class Timer22class Timer
41{23{
42 /**24 /**
43 * Remember times.25 * Remember times
44 *26 *
45 * We store for each category (primary key) the state, start/resume time and the total passed time.27 * We store for each category (primary key) the state, start/resume time and the total passed time.
46 *28 *
47 * @access protected29 * @var foo
48 */30 */
49 var $_times = array();31 var $_times = array();
5032
51
52 /**33 /**
53 * Constructor.34 * Constructor
54 *35 *
55 * @param string|NULL If a category is given the timer starts right away.36 * @param string|NULL If a category is given the timer starts right away.
56 */37 */
57 function Timer( $category = NULL )38 function Timer( $category = NULL )
58 {39 {
59 if( is_string($category) )40 if( is_string( $category ) )
60 {41 {
61 $this->start( $category );42 $this->start( $category );
62 }43 }
@@ -64,7 +45,7 @@
6445
6546
66 /**47 /**
67 * Reset a timer category.48 * Reset a timer category
68 */49 */
69 function reset( $category )50 function reset( $category )
70 {51 {
@@ -73,49 +54,44 @@
7354
7455
75 /**56 /**
76 * Start a timer.57 * Start a timer
77 */58 */
78 function start( $category, $log = true )59 function start( $category, $log = true )
79 {60 {
80 global $Debuglog;
81 if( $log && is_object( $Debuglog ) ) $Debuglog->add( 'Starting timer '.$category, 'timer' );
82 $this->reset( $category );61 $this->reset( $category );
83 $this->resume( $category );62 $this->resume( $category );
84 }63 }
8564
8665
87 /**66 /**
88 * Stops a timer category. It may me resumed later on, see {@link resume()}. This is an alias for {@link pause()}.67 * Stops a timer category
68 *
69 * The timer may me resumed later on, see {@link resume()}. This is an alias for {@link pause()}.
89 *70 *
90 * @return boolean false, if the timer had not been started.71 * @return boolean false, if the timer had not been started.
91 */72 */
92 function stop( $category )73 function stop( $category )
93 {74 {
94 global $Debuglog;
95
96 if( ! $this->pause( $category ) )75 if( ! $this->pause( $category ) )
97 return false;76 return false;
9877
99 if( is_object( $Debuglog ) )
100 {
101 $Debuglog->add( 'Stopped timer '.$category.' at '.$this->get_duration( $category, 3 ), 'timer' );
102 }
103
104 return true;78 return true;
105 }79 }
10680
10781
108 /**82 /**
109 * Pauses a timer category. It may me resumed later on, see {@link resume()}.83 * Pause a timer category
110 *84 *
111 * NOTE: The timer needs to be started, either through the {@link Timer() Constructor} or the {@link start()} method.85 * It may me resumed later on, see {@link resume()}. NOTE: The timer needs to be started,
86 * either through the {@link Timer() Constructor} or the {@link start()} method.
112 *87 *
113 * @return boolean false, if the timer had not been started.88 * @return boolean false, if the timer had not been started.
114 */89 */
115 function pause( $category )90 function pause( $category )
116 {91 {
117 if( !isset($this->_times[$category]['resumed']) )92 if( ! isset( $this->_times[$category]['resumed'] ) )
118 { // Timer has not been started!93 {
94 // Timer has not been started!
119 return false;95 return false;
120 }96 }
121 $since_resume = $this->get_current_microtime() - $this->_times[$category]['resumed'];97 $since_resume = $this->get_current_microtime() - $this->_times[$category]['resumed'];
@@ -127,26 +103,25 @@
127103
128104
129 /**105 /**
130 * Resumes the timer on a category.106 * Resume the timer on a category
131 */107 */
132 function resume( $category )108 function resume( $category )
133 {109 {
134 if( !isset($this->_times[$category]['total']) )110 if( ! isset( $this->_times[$category]['total'] ) )
135 {111 {
136 $this->start($category);112 $this->start( $category );
137 }113 }
138 else114 else
139 {115 {
140 $this->_times[$category]['resumed'] = $this->get_current_microtime();116 $this->_times[$category]['resumed'] = $this->get_current_microtime();
141 $this->_times[$category]['count']++;117 $this->_times[$category]['count']++;
142
143 $this->_times[$category]['state'] = 'running';118 $this->_times[$category]['state'] = 'running';
144 }119 }
145 }120 }
146121
147122
148 /**123 /**
149 * Get the duration for a given category.124 * Get the duration for a given category
150 *125 *
151 * @param string Category name126 * @param string Category name
152 * @param integer Number of decimals after dot.127 * @param integer Number of decimals after dot.
@@ -154,12 +129,13 @@
154 */129 */
155 function get_duration( $category, $decimals = 3 )130 function get_duration( $category, $decimals = 3 )
156 {131 {
157 return number_format( $this->get_microtime($category), $decimals ); // TODO: decimals/seperator by locale!132 // @todo (0000) decimals/seperator by locale!
133 return number_format( $this->get_microtime( $category ), $decimals );
158 }134 }
159135
160136
161 /**137 /**
162 * Get number of timer resumes (includes start).138 * Get number of timer resumes (includes start)
163 *139 *
164 * @return integer140 * @return integer
165 */141 */
@@ -175,41 +151,40 @@
175151
176152
177 /**153 /**
178 * Get the time in microseconds that was spent in the given category.154 * Get the time in microseconds that was spent in the given category
179 *155 *
180 * @return float156 * @return float
181 */157 */
182 function get_microtime( $category )158 function get_microtime( $category )
183 {159 {
184 switch( $this->get_state($category) )160 switch( $this->get_state( $category ) )
185 {161 {
186 case 'running':162 case 'running':
187 // The timer is running, we need to return the additional time since the last resume.163 // The timer is running, we need to return the additional time since the last resume
188 return $this->_times[$category]['total']164 return $this->_times[$category]['total'] + $this->get_current_microtime() - $this->_times[$category]['resumed'];
189 + $this->get_current_microtime() - $this->_times[$category]['resumed'];
190165
191 case 'paused':166 case 'paused':
192 return $this->_times[$category]['total'];167 return $this->_times[$category]['total'];
193168
194 default:169 default:
195 return (float)0;170 return (float)0;
196 }171 }
197 }172 }
198173
199174
200 /**175 /**
201 * Get the state a category timer is in.176 * Get the state a category timer is in
202 *177 *
203 * @return string 'unknown', 'not initialised', 'running', 'paused'178 * @return string 'unknown', 'not initialised', 'running', 'paused'
204 */179 */
205 function get_state( $category )180 function get_state( $category )
206 {181 {
207 if( !isset($this->_times[$category]) )182 if( ! isset( $this->_times[$category] ) )
208 {183 {
209 return 'unknown';184 return 'unknown';
210 }185 }
211186
212 if( !isset($this->_times[$category]['state']) )187 if( ! isset( $this->_times[$category]['state'] ) )
213 {188 {
214 return 'not initialised';189 return 'not initialised';
215 }190 }
@@ -219,7 +194,7 @@
219194
220195
221 /**196 /**
222 * Get a list of used categories.197 * Get a list of used categories
223 *198 *
224 * @return array199 * @return array
225 */200 */
@@ -236,9 +211,10 @@
236 */211 */
237 function get_current_microtime()212 function get_current_microtime()
238 {213 {
239 list($usec, $sec) = explode(' ', microtime());214 list( $usec, $sec ) = explode( ' ', microtime() );
240 return ((float)$usec + (float)$sec);215 return ( (float)$usec + (float)$sec );
241 }216 }
217
242}218}
243219
244?>
245\ No newline at end of file220\ No newline at end of file
221?>
246222
=== modified file 'qp_inc/_core/model/dataobjects/_dataobject.class.php'
--- qp_inc/_core/model/dataobjects/_dataobject.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/dataobjects/_dataobject.class.php 2013-03-20 18:13:29 +0000
@@ -1,89 +1,86 @@
1<?php1<?php
2/**2/**
3 * This file implements the abstract DataObject base class.3 * This file implements the abstract DataObject base class
4 *
5 * This file is part of Quam Plures - {@link http://quamplures.net/}
6 * See also {@link https://launchpad.net/quam-plures}.
7 *
8 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
9 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
10 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
11 * Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.
12 *
13 * {@internal License choice
14 * - If you have received this file as part of a package, please find the license.txt file in
15 * the same folder or the closest folder above for complete license terms.
16 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
17 * then you must choose one of the following licenses before using the file:
18 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
19 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
20 * }}
21 *
22 * {@internal Open Source relicensing agreement:
23 * Daniel HAHLER grants Francois PLANQUE the right to license
24 * Daniel HAHLER's contributions to this file and the b2evolution project
25 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
26 *
27 * PROGIDISTRI S.A.S. grants Francois PLANQUE the right to license
28 * PROGIDISTRI S.A.S.'s contributions to this file and the b2evolution project
29 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
30 * }}
31 *
32 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
33 * @author fplanque: Francois PLANQUE
34 * @author blueyed: Daniel HAHLER
35 * @author mbruneau: Marc BRUNEAU / PROGIDISTRI
36 *
37 * @package pond
38 */
39if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
40
41/**
42 * Data Object Base Class
43 *4 *
44 * This is typically an abstract class, useful only when derived.5 * This is typically an abstract class, useful only when derived.
45 *6 *
46 * @version beta7 * @todo (1111) vars type 'foo' need useful/valid descriptions
47 * @abstract8 * @author {@link http://wonderwinds.com/ Ed Bennett}
9 * @author {@link http://progidistri.com/ PROGIDISTRI}
10 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
11 * @author {@link http://fplanque.net/ Francois PLANQUE}
12 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
13 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
14 * @package core
15 */
16if(!defined('QP_MAIN_INIT')) die('fail');
17
18/**
19 * DataObject base class
48 *20 *
49 * @package pond21 * @package core
50 */22 */
51class DataObject23class DataObject
52{24{
53 /**25 /**
54 * Unique ID of object in database26 * Unique ID of object in database
55 *27 *
56 * Please use get/set functions to read or write this param28 * This will be the ID in the DB. Please use get/set functions to read or write this param
57 *29 *
58 * @var int30 * @var integer
59 * @access protected
60 */31 */
61 var $ID = 0; // This will be the ID in the DB32 var $ID = 0;
6233 /**
63 /**#@+34 * FIX THIS
64 * @access private35 * @var foo
65 */36 */
66 var $dbtablename;37 var $dbtablename;
38 /**
39 * FIX THIS
40 * @var foo
41 */
67 var $dbprefix;42 var $dbprefix;
43 /**
44 * FIX THIS
45 * @var foo
46 */
68 var $dbIDname;47 var $dbIDname;
48 /**
49 * FIX THIS
50 * @var foo
51 */
69 var $datecreated_field;52 var $datecreated_field;
53 /**
54 * FIX THIS
55 * @var foo
56 */
70 var $datemodified_field;57 var $datemodified_field;
58 /**
59 * FIX THIS
60 * @var foo
61 */
71 var $creator_field;62 var $creator_field;
63 /**
64 * FIX THIS
65 * @var foo
66 */
72 var $lasteditor_field;67 var $lasteditor_field;
68 /**
69 * FIX THIS
70 * @var foo
71 */
73 var $dbchanges = array();72 var $dbchanges = array();
74 /**#@-*/
75
76 /**73 /**
77 * Relations that may restrict deletion.74 * Relations that may restrict deletion.
75 * @var foo
78 */76 */
79 var $delete_restrictions = array();77 var $delete_restrictions = array();
80
81 /**78 /**
82 * Relations that will cascade deletion.79 * Relations that will cascade deletion.
80 * @var foo
83 */81 */
84 var $delete_cascades = array();82 var $delete_cascades = array();
8583
86
87 /**84 /**
88 * Constructor85 * Constructor
89 *86 *
@@ -97,28 +94,29 @@
97 */94 */
98 function DataObject( $tablename, $prefix = '', $dbIDname = 'ID', $datecreated_field = '', $datemodified_field = '', $creator_field = '', $lasteditor_field = '' )95 function DataObject( $tablename, $prefix = '', $dbIDname = 'ID', $datecreated_field = '', $datemodified_field = '', $creator_field = '', $lasteditor_field = '' )
99 {96 {
100 $this->dbtablename = $tablename;97 $this->dbtablename = $tablename;
101 $this->dbprefix = $prefix;98 $this->dbprefix = $prefix;
102 $this->dbIDname = $dbIDname;99 $this->dbIDname = $dbIDname;
103 $this->datecreated_field = $datecreated_field;100 $this->datecreated_field = $datecreated_field;
104 $this->datemodified_field = $datemodified_field;101 $this->datemodified_field = $datemodified_field;
105 $this->creator_field = $creator_field;102 $this->creator_field = $creator_field;
106 $this->lasteditor_field = $lasteditor_field;103 $this->lasteditor_field = $lasteditor_field;
107 }104 }
108105
109106
110 /**107 /**
111 * Records a change that will need to be updated in the db108 * Records a change that will need to be updated in the db
112 *109 *
113 * @access protected
114 * @param string Name of parameter110 * @param string Name of parameter
115 * @param string DB field type ('string', 'number', 'date' )111 * @param string DB field type ('string', 'number', 'date' )
116 * @param mixed Pointer to value of parameter - dh> pointer? So it should be a reference? Would make sense IMHO anyway.. fp> I just wonder why it's not already a reference... :@112 * @param mixed Pointer to value of parameter - dh> pointer? So it should be a
113 * reference? Would make sense IMHO anyway.. fp> I just wonder why it's not already
114 * a reference... :@
117 */115 */
118 function dbchange( $dbfieldname, $dbfieldtype, $valuepointer ) // TODO: dh> value by reference? see above..116 function dbchange( $dbfieldname, $dbfieldtype, $valuepointer ) // @todo (0000) dh> value by reference? see above..
119 {117 {
120 $this->dbchanges[$dbfieldname]['type'] = $dbfieldtype;118 $this->dbchanges[$dbfieldname]['type'] = $dbfieldtype;
121 $this->dbchanges[$dbfieldname]['value'] = $valuepointer ;119 $this->dbchanges[$dbfieldname]['value'] = $valuepointer;
122 }120 }
123121
124122
@@ -130,24 +128,30 @@
130 */128 */
131 function dbupdate( $auto_track_modification = true )129 function dbupdate( $auto_track_modification = true )
132 {130 {
133 global $DB, $localtimenow, $current_User;131 global $current_User;
132 global $DB;
133 global $localtimenow;
134134
135 if( $this->ID == 0 ) { debug_die( 'New object cannot be updated!' ); }135 if( $this->ID == 0 ) { debug_die( 'New object cannot be updated!' ); }
136136
137 if( count( $this->dbchanges ) == 0 )137 if( count( $this->dbchanges ) == 0 )
138 {138 {
139 return NULL; // No changes!139 return NULL; // No changes!
140 }140 }
141141
142 if( $auto_track_modification )142 if( $auto_track_modification )
143 { // We wnat to track modification date and author automatically:143 {
144 if( !empty($this->datemodified_field) )144 // We want to track modification date and author automatically
145 { // We want to track modification date:145 if( ! empty( $this->datemodified_field ) )
146 $this->set_param( $this->datemodified_field, 'date', date('Y-m-d H:i:s',$localtimenow) );146 {
147 // We want to track modification date
148 $this->set_param( $this->datemodified_field, 'date', date( 'Y-m-d H:i:s', $localtimenow ) );
147 }149 }
148 if( !empty($this->lasteditor_field) && is_object($current_User) )150 if( ! empty( $this->lasteditor_field ) && is_object( $current_User ) )
149 { // We want to track last editor:151 {
150 // TODO: the current_User is not necessarily the last editor. Item::dbupdate() gets called after incrementing the view for example!152 // We want to track last editor
153 // @todo (0000) the current_User is not necessarily the last editor.
154 // Item::dbupdate() gets called after incrementing the view for example!
151 // fplanque: this should be handled by set() deciding wether the setting changes the last editor or not155 // fplanque: this should be handled by set() deciding wether the setting changes the last editor or not
152 $this->set_param( $this->lasteditor_field, 'number', $current_User->ID );156 $this->set_param( $this->lasteditor_field, 'number', $current_User->ID );
153 }157 }
@@ -156,10 +160,11 @@
156 $sql_changes = array();160 $sql_changes = array();
157 foreach( $this->dbchanges as $loop_dbfieldname => $loop_dbchange )161 foreach( $this->dbchanges as $loop_dbfieldname => $loop_dbchange )
158 {162 {
159 // Get changed value (we use eval() to allow constructs like $loop_dbchange['value'] = 'Group->get(\'ID\')'):163 // Get changed value
164 // (we use eval() to allow constructs like $loop_dbchange['value'] = 'Group->get(\'ID\')'):
160 eval( '$loop_value = $this->'.$loop_dbchange['value'].';' );165 eval( '$loop_value = $this->'.$loop_dbchange['value'].';' );
161 // Prepare matching statement:166 // Prepare matching statement
162 if( is_null($loop_value) )167 if( is_null( $loop_value ) )
163 {168 {
164 $sql_changes[] = $loop_dbfieldname.' = NULL ';169 $sql_changes[] = $loop_dbfieldname.' = NULL ';
165 }170 }
@@ -169,25 +174,24 @@
169 {174 {
170 case 'date':175 case 'date':
171 case 'string':176 case 'string':
172 $sql_changes[] = $loop_dbfieldname." = '".$DB->escape( $loop_value )."' ";177 $sql_changes[] = $loop_dbfieldname." = '".$DB->escape( $loop_value )."' ";
173 break;178 break;
174179
175 default:180 default:
176 $sql_changes[] = $loop_dbfieldname." = ".$DB->null($loop_value).' ';181 $sql_changes[] = $loop_dbfieldname." = ".$DB->null( $loop_value ).' ';
177 }182 }
178 }183 }
179 }184 }
180185
181 // Prepare full statement:186 // Prepare full statement
182 $sql = "UPDATE $this->dbtablename SET ". implode( ', ', $sql_changes ). "187 $sql = "UPDATE $this->dbtablename SET ". implode( ', ', $sql_changes ). " WHERE $this->dbIDname = $this->ID";
183 WHERE $this->dbIDname = $this->ID";
184188
185 if( ! $DB->query( $sql, 'DataObject::dbupdate()' ) )189 if( ! $DB->query( $sql, 'DataObject::dbupdate()' ) )
186 {190 {
187 return false;191 return false;
188 }192 }
189193
190 // Reset changes in object:194 // Reset changes in object
191 $this->dbchanges = array();195 $this->dbchanges = array();
192196
193 return true;197 return true;
@@ -195,35 +199,43 @@
195199
196200
197 /**201 /**
198 * Insert object into DB based on previously recorded changes.202 * Insert object into DB based on previously recorded changes
199 *203 *
200 * @return boolean true on success204 * @return boolean true on success
201 */205 */
202 function dbinsert()206 function dbinsert()
203 {207 {
204 global $DB, $localtimenow, $current_User;208 global $current_User;
209 global $DB;
210 global $localtimenow;
205211
206 if( $this->ID != 0 ) debug_die( 'Existing object cannot be inserted!' );212 if( $this->ID != 0 ) debug_die( 'Existing object cannot be inserted!' );
207213
208 if( !empty($this->datecreated_field) )214 if( ! empty( $this->datecreated_field ) )
209 { // We want to track creation date:215 {
210 $this->set_param( $this->datecreated_field, 'date', date('Y-m-d H:i:s',$localtimenow) );216 // We want to track creation date
211 }217 $this->set_param( $this->datecreated_field, 'date', date( 'Y-m-d H:i:s', $localtimenow ) );
212 if( !empty($this->datemodified_field) )218 }
213 { // We want to track modification date:219 if( ! empty( $this->datemodified_field ) )
214 $this->set_param( $this->datemodified_field, 'date', date('Y-m-d H:i:s',$localtimenow) );220 {
215 }221 // We want to track modification date
216 if( !empty($this->creator_field) )222 $this->set_param( $this->datemodified_field, 'date', date( 'Y-m-d H:i:s', $localtimenow ) );
217 { // We want to track creator:223 }
218 if( empty($this->creator_user_ID) )224 if( ! empty( $this->creator_field ) )
219 { // No creator assigned yet, use current user:225 {
226 // We want to track creator
227 if( empty( $this->creator_user_ID ) )
228 {
229 // No creator assigned yet, use current user
220 $this->set_param( $this->creator_field, 'number', $current_User->ID );230 $this->set_param( $this->creator_field, 'number', $current_User->ID );
221 }231 }
222 }232 }
223 if( !empty($this->lasteditor_field) )233 if( ! empty( $this->lasteditor_field ) )
224 { // We want to track last editor:234 {
225 if( empty($this->lastedit_user_ID) )235 // We want to track last editor
226 { // No editor assigned yet, use current user:236 if( empty( $this->lastedit_user_ID ) )
237 {
238 // No editor assigned yet, use current user
227 $this->set_param( $this->lasteditor_field, 'number', $current_User->ID );239 $this->set_param( $this->lasteditor_field, 'number', $current_User->ID );
228 }240 }
229 }241 }
@@ -232,11 +244,12 @@
232 $sql_values = array();244 $sql_values = array();
233 foreach( $this->dbchanges as $loop_dbfieldname => $loop_dbchange )245 foreach( $this->dbchanges as $loop_dbfieldname => $loop_dbchange )
234 {246 {
235 // Get changed value (we use eval() to allow constructs like $loop_dbchange['value'] = 'Group->get(\'ID\')'):247 // Get changed value
248 // (we use eval() to allow constructs like $loop_dbchange['value'] = 'Group->get(\'ID\')'):
236 eval( '$loop_value = $this->'. $loop_dbchange['value'].';' );249 eval( '$loop_value = $this->'. $loop_dbchange['value'].';' );
237 // Prepare matching statement:250 // Prepare matching statement
238 $sql_fields[] = $loop_dbfieldname;251 $sql_fields[] = $loop_dbfieldname;
239 if( is_null($loop_value) )252 if( is_null( $loop_value ) )
240 {253 {
241 $sql_values[] = 'NULL';254 $sql_values[] = 'NULL';
242 }255 }
@@ -246,16 +259,16 @@
246 {259 {
247 case 'date':260 case 'date':
248 case 'string':261 case 'string':
249 $sql_values[] = $DB->quote( $loop_value );262 $sql_values[] = $DB->quote( $loop_value );
250 break;263 break;
251264
252 default:265 default:
253 $sql_values[] = $DB->null( $loop_value );266 $sql_values[] = $DB->null( $loop_value );
254 }267 }
255 }268 }
256 }269 }
257270
258 // Prepare full statement:271 // Prepare full statement
259 $sql = "INSERT INTO {$this->dbtablename} (". implode( ', ', $sql_fields ). ") VALUES (". implode( ', ', $sql_values ). ")";272 $sql = "INSERT INTO {$this->dbtablename} (". implode( ', ', $sql_fields ). ") VALUES (". implode( ', ', $sql_values ). ")";
260273
261 if( ! $DB->query( $sql, 'DataObject::dbinsert()' ) )274 if( ! $DB->query( $sql, 'DataObject::dbinsert()' ) )
@@ -266,7 +279,7 @@
266 // store ID for newly created db record279 // store ID for newly created db record
267 $this->ID = $DB->insert_id;280 $this->ID = $DB->insert_id;
268281
269 // Reset changes in object:282 // Reset changes in object
270 $this->dbchanges = array();283 $this->dbchanges = array();
271284
272 return true;285 return true;
@@ -274,7 +287,7 @@
274287
275288
276 /**289 /**
277 * Inserts or Updates depending on object state.290 * Inserts or Updates depending on object state
278 *291 *
279 * @uses dbinsert()292 * @uses dbinsert()
280 * @uses dbupdate()293 * @uses dbupdate()
@@ -283,55 +296,57 @@
283 function dbsave()296 function dbsave()
284 {297 {
285 if( $this->ID == 0 )298 if( $this->ID == 0 )
286 { // Object not serialized yet, let's insert!299 {
300 // Object not serialized yet, let's insert!
287 return $this->dbinsert();301 return $this->dbinsert();
288 }302 }
289 else303 else
290 { // Object already serialized, let's update!304 {
305 // Object already serialized, let's update!
291 return $this->dbupdate();306 return $this->dbupdate();
292 }307 }
293 }308 }
294309
295310
296 /**311 /**
297 * Delete object from DB.312 * Delete object from DB
298 *313 *
299 * @return boolean true on success314 * @return boolean true on success
300 */315 */
301 function dbdelete()316 function dbdelete()
302 {317 {
303 global $DB, $Messages, $app_db_config;318 global $app_db_config;
319 global $DB;
320 global $Messages;
304321
305 if( $this->ID == 0 ) { debug_die( 'Non persistant object cannot be deleted!' ); }322 if( $this->ID == 0 ) { debug_die( 'Non persistant object cannot be deleted!' ); }
306323
307 if( count($this->delete_cascades) )324 if( count( $this->delete_cascades ) )
308 { // The are cascading deletes to be performed325 {
309326 // The are cascading deletes to be performed; start transaction
310 // Start transaction:
311 $DB->begin();327 $DB->begin();
312328
313 foreach( $this->delete_cascades as $restriction )329 foreach( $this->delete_cascades as $restriction )
314 {330 {
315 if( !isset( $app_db_config['aliases'][$restriction['table']] ) )331 if( ! isset( $app_db_config['aliases'][$restriction['table']] ) )
316 { // We have no declaration for this table, we consider we don't deal with this table in this app:332 {
333 // We have no declaration for this table, we consider we don't deal with this table in this app
317 continue;334 continue;
318 }335 }
319336
320 $DB->query( '337 $DB->query( 'DELETE FROM '.$restriction['table'].' WHERE '.$restriction['fk'].' = '.$this->ID, 'Cascaded delete' );
321 DELETE FROM '.$restriction['table'].'
322 WHERE '.$restriction['fk'].' = '.$this->ID,
323 'Cascaded delete' );
324 }338 }
325 }339 }
326340
327 // Delete this (main/parent) object:341 // Delete this (main/parent) object
328 $DB->query( "342 $DB->query( "
329 DELETE FROM $this->dbtablename343 DELETE FROM $this->dbtablename
330 WHERE $this->dbIDname = $this->ID",344 WHERE $this->dbIDname = $this->ID",
331 'Main delete' );345 'Main delete' );
332346
333 if( count($this->delete_cascades) )347 if( count( $this->delete_cascades ) )
334 { // There were cascading deletes348 {
349 // There were cascading deletes
335350
336 // End transaction:351 // End transaction:
337 $DB->commit();352 $DB->commit();
@@ -347,36 +362,42 @@
347 /**362 /**
348 * Check relations for restrictions or cascades363 * Check relations for restrictions or cascades
349 *364 *
365 * The $verbose_callbacks array is as follows:
366 * <ul> <li>Array keys (string): Foreign key this callback should apply to.</li>
367 * <li>Array values: Arrays with the following keys:
368 * <ul><li>'cb' (callback): Callback to call. Should take one array argument, which
369 * will contain the following keys:</li>
370 * <li>'fk': The foreign key.</li>
371 * <li>'table': The SQL table for this relation.</li>
372 * <li>'msg': A format string -- a base message to be displayed.It normally shows
373 * the number of results.</li>
374 * <li>'id': The ID of this object.</li>
375 * </li></ul></ul>
376 *
350 * @param string Which relation should be checked ('delete_restrictions' or 'delete_cascades')?377 * @param string Which relation should be checked ('delete_restrictions' or 'delete_cascades')?
351 * @param string An array of foreign key checks to skip.378 * @param string An array of foreign key checks to skip.
352 * @param array An array of callbacks used to display more information about a relation.379 * @param array An array of callbacks used to display more information about a relation.
353 * - Array keys (string): Foreign key this callback should apply to.
354 * - Array values: Arrays with the following keys:
355 * - 'cb' (callback): Callback to call. Should take one array argument, which
356 * will contain the following keys:
357 * - 'fk': The foreign key.
358 * - 'table': The SQL table for this relation.
359 * - 'msg': A format string -- a base message to be displayed.
360 * It normally shows the number of results.
361 * - 'id': The ID of this object.
362 */380 */
363 function check_relations( $what, $ignore = array(), $verbose_callbacks = array() )381 function check_relations( $what, $ignore = array(), $verbose_callbacks = array() )
364 {382 {
365 global $DB, $Messages;383 global $DB;
384 global $Messages;
366385
367 foreach( $this->$what as $restriction )386 foreach( $this->$what as $restriction )
368 {387 {
369 if( in_array( $restriction['fk'], $ignore ) )388 if( in_array( $restriction['fk'], $ignore ) )
370 { // Skip this relation check.389 {
390 // Skip this relation check
371 continue;391 continue;
372 }392 }
373393
374 if( ! isset( $verbose_callbacks[$restriction['fk']] ) )394 if( ! isset( $verbose_callbacks[$restriction['fk']] ) )
375 { // We do not want to display detailed info, just the result count:395 {
396 // We do not want to display detailed info, just the result count
376 $count = $DB->get_var(397 $count = $DB->get_var(
377 'SELECT COUNT(*)398 'SELECT COUNT(*)
378 FROM '.$restriction['table'].'399 FROM '.$restriction['table'].'
379 WHERE '.$restriction['fk'].' = '.$this->ID,400 WHERE '.$restriction['fk'].' = '.$this->ID,
380 0, 0, 'restriction/cascade check' );401 0, 0, 'restriction/cascade check' );
381 if( $count )402 if( $count )
382 {403 {
@@ -384,7 +405,8 @@
384 }405 }
385 }406 }
386 else407 else
387 { // We want verbose information.408 {
409 // We want verbose information.
388 // We just will call the callback, providing some410 // We just will call the callback, providing some
389 // information about this object:411 // information about this object:
390 call_user_func( $verbose_callbacks[$restriction['fk']]['cb'],412 call_user_func( $verbose_callbacks[$restriction['fk']]['cb'],
@@ -411,16 +433,17 @@
411 $this->check_relations( 'delete_restrictions', $ignore );433 $this->check_relations( 'delete_restrictions', $ignore );
412434
413 if( $Messages->count('restrict') )435 if( $Messages->count('restrict') )
414 { // There are restrictions:436 {
437 // There are restrictions:
415 $Messages->head = array(438 $Messages->head = array(
416 'container' => $restrict_title,439 'container' => $restrict_title,
417 'restrict' => T_('The following relations prevent deletion:')440 'restrict' => T_('The following relations prevent deletion:')
418 );441 );
419 $Messages->foot = T_('Please delete related objects before you proceed.');442 $Messages->foot = T_('Please delete related objects before you proceed.');
420 return false; // Can't delete443 return false; // Can't delete
421 }444 }
422445
423 return true; // can delete446 return true; // can delete
424 }447 }
425448
426449
@@ -444,7 +467,8 @@
444 $this->check_relations( 'delete_cascades' );467 $this->check_relations( 'delete_cascades' );
445468
446 if( $Messages->count('restrict') )469 if( $Messages->count('restrict') )
447 { // The will be cascading deletes, issue WARNING:470 {
471 // The will be cascading deletes, issue WARNING
448 echo '<h3>'.T_('WARNING: Deleting this object will also delete:').'</h3>';472 echo '<h3>'.T_('WARNING: Deleting this object will also delete:').'</h3>';
449 $Messages->display( '', '', true, 'restrict', NULL, NULL, NULL );473 $Messages->display( '', '', true, 'restrict', NULL, NULL, NULL );
450 }474 }
@@ -465,7 +489,7 @@
465489
466 $Form->begin_form( 'inline' );490 $Form->begin_form( 'inline' );
467 $Form->hiddens_by_key( $hiddens );491 $Form->hiddens_by_key( $hiddens );
468 if( !empty( $cancel_action ) )492 if( ! empty( $cancel_action ) )
469 {493 {
470 $Form->hidden( 'action', $cancel_action );494 $Form->hidden( 'action', $cancel_action );
471 }495 }
@@ -500,7 +524,7 @@
500 function dget( $parname, $format = 'htmlbody' )524 function dget( $parname, $format = 'htmlbody' )
501 {525 {
502 // Note: we call get again because of derived objects specific handlers !526 // Note: we call get again because of derived objects specific handlers !
503 return format_to_output( $this->get($parname), $format );527 return format_to_output( $this->get( $parname ), $format );
504 }528 }
505529
506530
@@ -513,7 +537,7 @@
513 function disp( $parname, $format = 'htmlbody' )537 function disp( $parname, $format = 'htmlbody' )
514 {538 {
515 // Note: we call get again because of derived objects specific handlers !539 // Note: we call get again because of derived objects specific handlers !
516 echo format_to_output( $this->get($parname), $format );540 echo format_to_output( $this->get( $parname ), $format );
517 }541 }
518542
519543
@@ -534,90 +558,74 @@
534558
535559
536 /**560 /**
537 * Set param value.561 * Set param value
538 *562 *
539 * @param string Name of parameter563 * @param string Name of parameter
540 * @param string DB field type ('string', 'number', 'date' )564 * @param string DB field type ('string', 'number', 'date')
541 * @param mixed Value of parameter565 * @param mixed Value of parameter
542 * @param boolean true to set to NULL if empty string value566 * @param boolean true to set to NULL if empty string value
543 * @return boolean true, if value has been set/changed, false if not.567 * @return boolean true, if value has been set/changed, false if not.
544 */568 */
545 function set_param( $parname, $fieldtype, $parvalue, $make_null = false )569 function set_param( $parname, $fieldtype, $parvalue, $make_null = false )
546 {570 {
547 global $Debuglog;
548
549 $dbfield = $this->dbprefix.$parname;571 $dbfield = $this->dbprefix.$parname;
550572
551 // Set value:573 // Set value. fplanque: Note: I am changing the "make NULL" test to differentiate
552 // fplanque: Note: I am changing the "make NULL" test to differentiate between 0 and NULL .574 // between 0 and NULL. There might be side effects. In this case it would be
553 // There might be side effects. In this case it would be better to fix them before coming here.575 // better to fix them before coming here. i-e: transform 0 to ''
554 // i-e: transform 0 to ''576 $new_value = ( $make_null && ( $parvalue === '' ) ) ? NULL : $parvalue;
555 $new_value = ($make_null && ($parvalue === '')) ? NULL : $parvalue;
556577
557 /* Tblue> Problem: All class member variables originating from the578 // Tblue> Problem: All class member variables originating from the DB are strings
558 * DB are strings (unless they were NULL in the DB,579 // (unless they were NULL in the DB, then they are set to NULL by the PHP MySQL
559 * then they are set to NULL by the PHP MySQL580 // extension). If we pass an integer or a double to this function, the corresponding
560 * extension).581 // member variable gets changed on every call, because its type is 'string' and
561 * If we pass an integer or a double to this function,582 // we compare using the === operator. Using the == operator would be a bad idea,
562 * the corresponding member variable gets changed583 // though, because somebody could pass a NULL value to this function. If the member
563 * on every call, because its type is 'string' and584 // variable then is set to 0, then 0 equals NULL and the member variable does not
564 * we compare using the === operator. Using the585 // get updated at all! Thus, using the === operator is correct.
565 * == operator would be a bad idea, though, because586 // Solution: If $fieldtype is 'number' and the type of the passed value is either
566 * somebody could pass a NULL value to this function.587 // integer or double, we convert it to a string (no data loss). The member variable and
567 * If the member variable then is set to 0, then588 // the passed value can then be correctly compared using the === operator.
568 * 0 equals NULL and the member variable does not589 // fp> It would be nicer to convert numeric values to ints & floats at load time in
569 * get updated at all!590 // class constructor x=(int)$y->value or sth.
570 * Thus, using the === operator is correct.591 // THIS IS EXPERIMENTAL! Feel free to revert if something does not
571 * Solution: If $fieldtype is 'number' and the type of the592 // work as expected.
572 * passed value is either integer or double, we
573 * convert it to a string (no data loss). The
574 * member variable and the passed value can then
575 * be correctly compared using the === operator.
576 * fp> It would be nicer to convert numeric values to ints & floats at load time in class constructor x=(int)$y->value or sth.
577 * THIS IS EXPERIMENTAL! Feel free to revert if something does not
578 * work as expected.
579 */
580 if( $fieldtype == 'number' && ( is_int( $new_value ) || is_float( $new_value ) ) )593 if( $fieldtype == 'number' && ( is_int( $new_value ) || is_float( $new_value ) ) )
581 {594 {
582 settype( $new_value, 'string' );595 settype( $new_value, 'string' );
583 }596 }
584597
585/* >old598 /*
586 if( !isset($this->$parname) )599 old way
587 { // This property has never been set before, set it to NULL now in order for tests to work:600 if( ! isset( $this->$parname ) )
601 {
602 // This property has never been set before, set it to NULL now in order for tests to work:
588 $this->$parname = NULL;603 $this->$parname = NULL;
589 }604 }
590605
591606 @todo (0000) blueyed> there's a bug here: you cannot use set_param('foo',
592 /* blueyed>607 'number', 0), if the $parname member has not been set before or is null!! What
593 TODO: there's a bug here: you cannot use set_param('foo', 'number', 0), if the $parname member608 about just:( isset( $this->$parname ) && $this->$parname === $new_value )
594 has not been set before or is null!!609 This would also eliminate the isset() check from above. IIRC you've once said
595 What about just:610 here that '===' would be too expensive and I would misuse the DataObjects, but
596 ( isset($this->$parname) && $this->$parname === $new_value )611 IMHO what we have now is not much faster and buggy anyway. fp> okay let's give
597 This would also eliminate the isset() check from above.612 it a try...
598 IIRC you've once said here that '===' would be too expensive and I would misuse the DataObjects,613 if( ( ! is_null( $new_value ) && $this->$parname == $new_value )
599 but IMHO what we have now is not much faster and buggy anyway..614 || ( is_null( $this->$parname ) && is_null( $new_value ) ) )
600 fp> okay let's give it a try...615 */
601 if( (!is_null($new_value) && $this->$parname == $new_value)616
602 || (is_null($this->$parname) && is_null($new_value)) )617 if( ( isset( $this->$parname ) && $this->$parname === $new_value )
603<old */618 || ( ! isset( $this->$parname ) && ! isset( $new_value ) ) )
604 if( (isset($this->$parname) && $this->$parname === $new_value)619 {
605 || ( ! isset($this->$parname) && ! isset($new_value) ) )620 // Value has not changed (we need 2 tests, for NULL and for NOT NULL value pairs)
606 { // Value has not changed (we need 2 tests, for NULL and for NOT NULL value pairs)
607 $Debuglog->add( $this->dbtablename.' object, already set to same value: '.$parname.'/'.$dbfield.' = '.var_export( @$this->$parname, true ), 'dataobjects' );
608
609 return false;621 return false;
610 }622 }
611 else623 else
612 {624 {
613 // Set the value in the object:625 // Set the value in the object
614 $Debuglog->add( $this->dbtablename.' object, setting param '
615 .$parname.'/'.$dbfield.' to '.var_export( $new_value, true )
616 .' (old: '.( isset( $this->$parname ) ? var_export( $this->$parname, true ) : 'NULL' )
617 .')', 'dataobjects' );
618 $this->$parname = $new_value;626 $this->$parname = $new_value;
619627
620 // Remember change for later db update:628 // Remember change for later db update
621 $this->dbchange( $dbfield, $fieldtype, $parname );629 $this->dbchange( $dbfield, $fieldtype, $parname );
622630
623 return true;631 return true;
@@ -626,7 +634,7 @@
626634
627635
628 /**636 /**
629 * Set a parameter from a Request form value.637 * Set a parameter from a Request form value
630 *638 *
631 * @param string Dataobject parameter name639 * @param string Dataobject parameter name
632 * @param string Request parameter name (NULL means to use Dataobject param name with its prefix)640 * @param string Request parameter name (NULL means to use Dataobject param name with its prefix)
@@ -635,17 +643,17 @@
635 */643 */
636 function set_from_Request( $parname, $var = NULL, $make_null = false )644 function set_from_Request( $parname, $var = NULL, $make_null = false )
637 {645 {
638 if( empty($var) )646 if( empty( $var ) )
639 {647 {
640 $var = $this->dbprefix.$parname;648 $var = $this->dbprefix.$parname;
641 }649 }
642650
643 return $this->set( $parname, get_param($var), $make_null );651 return $this->set( $parname, get_param( $var ), $make_null );
644 }652 }
645653
646654
647 /**655 /**
648 * Template function: Displays object ID.656 * Template function: Displays object ID
649 */657 */
650 function ID()658 function ID()
651 {659 {
@@ -662,47 +670,56 @@
662 $UserCache = & get_Cache( 'UserCache' );670 $UserCache = & get_Cache( 'UserCache' );
663671
664 // HANDLE CREATOR STUFF672 // HANDLE CREATOR STUFF
665 if( !empty($this->creator_field) && !empty($this->{$this->creator_field}) )673 if( ! empty( $this->creator_field ) && ! empty( $this->{$this->creator_field} ) )
666 { // We have a creator:674 {
675 // We have a creator
667 $creator_User = & $UserCache->get_by_ID( $this->{$this->creator_field} );676 $creator_User = & $UserCache->get_by_ID( $this->{$this->creator_field} );
668677
669 if( !empty($this->datecreated_field) && !empty($this->{$this->datecreated_field}) )678 if( ! empty( $this->datecreated_field ) && ! empty( $this->{$this->datecreated_field} ) )
670 { // We also have a create date:679 {
680 // We also have a create date
671 $history[0] = sprintf( T_('Created on %s by %s'), mysql2localedate( $this->{$this->datecreated_field} ),681 $history[0] = sprintf( T_('Created on %s by %s'), mysql2localedate( $this->{$this->datecreated_field} ),
672 $creator_User->dget('preferredname') );682 $creator_User->dget( 'preferredname' ) );
673 }683 }
674 else684 else
675 { // We only have a cretaor:685 {
676 $history[0] = sprintf( T_('Created by %s'), $creator_User->dget('preferredname') );686 // We only have a creator
687 $history[0] = sprintf( T_('Created by %s'), $creator_User->dget( 'preferredname' ) );
677 }688 }
678 }689 }
679 elseif( !empty($this->datecreated_field) && !empty($this->{$this->datecreated_field}) )690 elseif( ! empty( $this->datecreated_field ) && ! empty( $this->{$this->datecreated_field} ) )
680 { // We only have a create date:691 {
692 // We only have a create date
681 $history[0] = sprintf( T_('Created on %s'), mysql2localedate( $this->{$this->datecreated_field} ) );693 $history[0] = sprintf( T_('Created on %s'), mysql2localedate( $this->{$this->datecreated_field} ) );
682 }694 }
683695
684 // HANDLE LAST UPDATE STUFF696 // HANDLE LAST UPDATE STUFF
685 if( !empty($this->lasteditor_field) && !empty($this->{$this->lasteditor_field}) )697 if( ! empty( $this->lasteditor_field ) && ! empty( $this->{$this->lasteditor_field} ) )
686 { // We have a creator:698 {
699 // We have a creator
687 $creator_User = & $UserCache->get_by_ID( $this->{$this->lasteditor_field} );700 $creator_User = & $UserCache->get_by_ID( $this->{$this->lasteditor_field} );
688701
689 if( !empty($this->datemodified_field) && !empty($this->{$this->datemodified_field}) )702 if( ! empty( $this->datemodified_field ) && ! empty( $this->{$this->datemodified_field} ) )
690 { // We also have a create date:703 {
704 // We also have a create date
691 $history[1] = sprintf( T_('Last mod on %s by %s'), mysql2localedate( $this->{$this->datemodified_field} ),705 $history[1] = sprintf( T_('Last mod on %s by %s'), mysql2localedate( $this->{$this->datemodified_field} ),
692 $creator_User->dget('preferredname') );706 $creator_User->dget( 'preferredname' ) );
693 }707 }
694 else708 else
695 { // We only have a cretaor:709 {
696 $history[1] = sprintf( T_('Last mod by %s'), $creator_User->dget('preferredname') );710 // We only have a creator
711 $history[1] = sprintf( T_('Last mod by %s'), $creator_User->dget( 'preferredname' ) );
697 }712 }
698 }713 }
699 elseif( !empty($this->datemodified_field) && !empty($this->{$this->datemodified_field}) )714 elseif( ! empty( $this->datemodified_field ) && ! empty( $this->{$this->datemodified_field} ) )
700 { // We only have a create date:715 {
716 // We only have a create date
701 $history[1] = sprintf( T_('Last mod on %s'), mysql2localedate( $this->{$this->datemodified_field} ) );717 $history[1] = sprintf( T_('Last mod on %s'), mysql2localedate( $this->{$this->datemodified_field} ) );
702 }718 }
703719
704 return get_icon( 'history', $what = 'imgtag', array( 'title'=>implode( ' - ', $history ) ), true );720 return get_icon( 'history', $what = 'imgtag', array( 'title' => implode( ' - ', $history ) ), true );
705 }721 }
722
706}723}
707724
708?>725?>
709726
=== modified file 'qp_inc/_core/model/dataobjects/_dataobjectcache.class.php'
--- qp_inc/_core/model/dataobjects/_dataobjectcache.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/dataobjects/_dataobjectcache.class.php 2013-03-20 18:13:29 +0000
@@ -1,104 +1,95 @@
1<?php1<?php
2/**2/**
3 * This file implements the DataObjectCache class.3 * This file implements the DataObjectCache base class
4 *4 *
5 * This file is part of Quam Plures - {@link http://quamplures.net/}5 * @todo (1111) vars type 'foo' need useful/valid descriptions
6 * See also {@link https://launchpad.net/quam-plures}.6 * @author {@link http://wonderwinds.com/ Ed Bennett}
7 *7 * @author {@link http://progidistri.com/ PROGIDISTRI}
8 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}8 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
9 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}9 * @author {@link http://fplanque.net/ Francois PLANQUE}
10 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.10 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
11 * Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.11 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
12 *12 * @package core
13 * {@internal License choice
14 * - If you have received this file as part of a package, please find the license.txt file in
15 * the same folder or the closest folder above for complete license terms.
16 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
17 * then you must choose one of the following licenses before using the file:
18 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
19 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
20 * }}
21 *
22 * {@internal Open Source relicensing agreement:
23 * Daniel HAHLER grants Francois PLANQUE the right to license
24 * Daniel HAHLER's contributions to this file and the b2evolution project
25 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
26 *
27 * PROGIDISTRI S.A.S. grants Francois PLANQUE the right to license
28 * PROGIDISTRI S.A.S.'s contributions to this file and the b2evolution project
29 * under any OSI approved OSS license (http://www.opensource.org/licenses/).
30 * }}
31 *
32 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
33 * @author blueyed: Daniel HAHLER.
34 * @author fplanque: Francois PLANQUE
35 *
36 * @package pond
37 */13 */
38if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );14if(!defined('QP_MAIN_INIT')) die('fail');
3915
40/**16/**
41 * Data Object Cache Class17 * DataObjectCache base class
42 *18 *
43 * @todo dh> Provide iteration "interface"!19 * @package core
44 *
45 * @version beta
46 *
47 * @package pond
48 */20 */
49class DataObjectCache21class DataObjectCache
50{22{
23 /**
24 * FIX THIS
25 * @var foo
26 */
51 var $dbtablename;27 var $dbtablename;
28 /**
29 * FIX THIS
30 * @var foo
31 */
52 var $dbprefix;32 var $dbprefix;
33 /**
34 * FIX THIS
35 * @var foo
36 */
53 var $dbIDname;37 var $dbIDname;
54
55 /**38 /**
56 * Class name of objects in this cache:39 * Class name of objects in this cache:
40 * @var foo
57 */41 */
58 var $objtype;42 var $objtype;
59
60 /**43 /**
61 * Object array by ID44 * Object array by ID
45 * @var foo
62 */46 */
63 var $cache = array();47 var $cache = array();
64
65 /**48 /**
66 * Copy of previous object array49 * Copy of previous object array
67 * @see DataObjectCache::clear()50 * @see DataObjectCache::clear()
68 */51 */
69 var $shadow_cache = NULL;52 var $shadow_cache = NULL;
70
71 /**53 /**
72 * NON indexed object array54 * NON indexed object array
73 * @var array of DataObjects55 * @var array of DataObjects
74 */56 */
75 var $DataObject_array = array();57 var $DataObject_array = array();
7658 /**
77 /**
78 * Index of current iteration59 * Index of current iteration
79 * @see DataObjectCache::get_next()60 * @see DataObjectCache::get_next()
80 */61 */
81 var $current_idx = NULL;62 var $current_idx = NULL;
8263 /**
64 * FIX THIS
65 * @var foo
66 */
83 var $load_all = false;67 var $load_all = false;
68 /**
69 * FIX THIS
70 * @var foo
71 */
84 var $all_loaded = false;72 var $all_loaded = false;
8573 /**
8674 * FIX THIS
75 * @var foo
76 */
87 var $name_field;77 var $name_field;
78 /**
79 * FIX THIS
80 * @var foo
81 */
88 var $order_by;82 var $order_by;
89
90 /**83 /**
91 * The text that gets used for the "None" option in the objects options list.84 * The text that gets used for the "None" option in the objects options list
92 *85 *
93 * This is especially useful for i18n, because there are several "None"s!86 * This is especially useful for i18n, because there are several "None"s!
94 *87 *
95 * @var string88 * @var string
96 */89 */
97 var $none_option_text;90 var $none_option_text;
98
99 /**91 /**
100 * The value that gets used for the "None" option in the objects options list.92 * The value that gets used for the "None" option in the objects options list
101 *
102 * @var mixed93 * @var mixed
103 */94 */
104 var $none_option_value;95 var $none_option_value;
@@ -115,9 +106,18 @@
115 * @param string Name of the name field (including prefix)106 * @param string Name of the name field (including prefix)
116 * @param string field names or NULL to use name field107 * @param string field names or NULL to use name field
117 * @param string The text that gets used for the "None" option in the objects options list (Default: T_('None')).108 * @param string The text that gets used for the "None" option in the objects options list (Default: T_('None')).
118 * @param mixed The value that gets used for the "None" option in the objects options list.109 * @param mixed The value that gets used for the "None" option in the objects options list.
119 */110 */
120 function DataObjectCache( $objtype, $load_all, $tablename, $prefix = '', $dbIDname, $name_field = NULL, $order_by = '', $allow_none_text = NULL, $allow_none_value = '' )111 function DataObjectCache(
112 $objtype,
113 $load_all,
114 $tablename,
115 $prefix = '',
116 $dbIDname,
117 $name_field = NULL,
118 $order_by = '',
119 $allow_none_text = NULL,
120 $allow_none_value = '' )
121 {121 {
122 $this->objtype = $objtype;122 $this->objtype = $objtype;
123 $this->load_all = $load_all;123 $this->load_all = $load_all;
@@ -143,7 +143,7 @@
143 $this->order_by = $order_by;143 $this->order_by = $order_by;
144 }144 }
145145
146 if( isset($allow_none_text) )146 if( isset( $allow_none_text ) )
147 {147 {
148 $this->none_option_text = $allow_none_text;148 $this->none_option_text = $allow_none_text;
149 }149 }
@@ -160,7 +160,6 @@
160 function & new_obj( $row = NULL )160 function & new_obj( $row = NULL )
161 {161 {
162 $objtype = $this->objtype;162 $objtype = $this->objtype;
163
164 // Instantiate a custom object163 // Instantiate a custom object
165 $obj = new $objtype( $row ); // COPY !!164 $obj = new $objtype( $row ); // COPY !!
166165
@@ -173,24 +172,16 @@
173 */172 */
174 function load_all()173 function load_all()
175 {174 {
176 /**
177 * @var DB
178 */
179 global $DB;175 global $DB;
180 global $Debuglog;
181176
182 if( $this->all_loaded )177 if( $this->all_loaded )
183 { // Already loaded178 {
179 // Already loaded
184 return false;180 return false;
185 }181 }
186182
187 $this->clear( true );183 $this->clear( true );
188184 $sql = 'SELECT * FROM '.$this->dbtablename.' ORDER BY '.$this->order_by;
189 $Debuglog->add( get_class($this).' - Loading <strong>'.$this->objtype.'(ALL)</strong> into cache', 'dataobjects' );
190 $sql = 'SELECT *
191 FROM '.$this->dbtablename.'
192 ORDER BY '.$this->order_by;
193
194 foreach( $DB->get_results( $sql, OBJECT, 'Loading '.$this->objtype.'(ALL) into cache' ) as $row )185 foreach( $DB->get_results( $sql, OBJECT, 'Loading '.$this->objtype.'(ALL) into cache' ) as $row )
195 {186 {
196 // Instantiate a custom object187 // Instantiate a custom object
@@ -211,19 +202,14 @@
211 */202 */
212 function load_list( $req_list, $invert = false )203 function load_list( $req_list, $invert = false )
213 {204 {
214 global $DB, $Debuglog;205 global $DB;
215
216 $Debuglog->add( 'Loading <strong>'.$this->objtype.'('.( $invert ? 'ALL except ' : '' ).$req_list.')</strong> into cache', 'dataobjects' );
217206
218 if( empty( $req_list ) )207 if( empty( $req_list ) )
219 {208 {
220 return false;209 return false;
221 }210 }
222211
223 $sql = "SELECT *212 $sql = "SELECT * FROM $this->dbtablename WHERE $this->dbIDname ".( $invert ? 'NOT ' : '' )."IN ( $req_list )";
224 FROM $this->dbtablename
225 WHERE $this->dbIDname ".( $invert ? 'NOT ' : '' )."IN ($req_list)";
226
227 foreach( $DB->get_results( $sql ) as $row )213 foreach( $DB->get_results( $sql ) as $row )
228 {214 {
229 // Instantiate a custom object215 // Instantiate a custom object
@@ -233,19 +219,17 @@
233219
234220
235 /**221 /**
236 * Get an array of all (loaded) IDs.222 * Get an array of all (loaded) IDs
237 *223 *
238 * @return array224 * @return array
239 */225 */
240 function get_ID_array()226 function get_ID_array()
241 {227 {
242 $IDs = array();228 $IDs = array();
243
244 foreach( $this->cache as $obj )229 foreach( $this->cache as $obj )
245 {230 {
246 $IDs[] = $obj->ID;231 $IDs[] = $obj->ID;
247 }232 }
248
249 return $IDs;233 return $IDs;
250 }234 }
251235
@@ -255,26 +239,21 @@
255 */239 */
256 function add( & $Obj )240 function add( & $Obj )
257 {241 {
258 global $Debuglog;242 if( is_null( $Obj->ID ) ) // value 0 is used by item preview
259
260 if( is_null($Obj->ID) ) // value 0 is used by item preview
261 {243 {
262 $Debuglog->add( 'No object to add!', 'dataobjects' );
263 return false;244 return false;
264 }245 }
265246
266 // fplanque: I don't want an extra (and expensive) comparison here. $this->cache[$Obj->ID] === $Obj.247 // fplanque: I don't want an extra (and expensive) comparison here. $this->cache[$Obj->ID] === $Obj.
267 // If you need this you're probably misusing the cache.248 // If you need this you're probably misusing the cache.
268 if( isset($this->cache[$Obj->ID]) )249 if( isset( $this->cache[$Obj->ID] ) )
269 {250 {
270 $Debuglog->add( $this->objtype.': Object with ID '.$Obj->ID.' is already cached', 'dataobjects' );
271 return false;251 return false;
272 }252 }
273253
274 // If the object is valid and not already cached:254 // If the object is valid and not already cached, Add object to cache
275 // Add object to cache:
276 $this->cache[$Obj->ID] = & $Obj;255 $this->cache[$Obj->ID] = & $Obj;
277 // Add a reference in the object list:256 // Add a reference in the object list
278 $this->DataObject_array[] = & $Obj;257 $this->DataObject_array[] = & $Obj;
279258
280 return true;259 return true;
@@ -282,36 +261,40 @@
282261
283262
284 /**263 /**
285 * Instantiate a DataObject from a table row and then cache it.264 * Instantiate a DataObject from a table row and then cache it
286 *265 *
287 * @param Object Database row266 * @param Object Database row
288 * @return Object267 * @return Object
289 */268 */
290 function & instantiate( & $db_row )269 function & instantiate( & $db_row )
291 {270 {
292 if( is_null($db_row) )271 if( is_null( $db_row ) )
293 { // we can't access NULL as an object272 {
273 // we can't access NULL as an object
294 return $db_row;274 return $db_row;
295 }275 }
296276
297 // Get ID of the object we'ere preparing to instantiate...277 // Get ID of the object we'ere preparing to instantiate...
298 $obj_ID = $db_row->{$this->dbIDname};278 $obj_ID = $db_row->{$this->dbIDname};
299279
300 if( is_null($obj_ID) ) // value 0 is used for item preview280 if( is_null( $obj_ID ) ) // value 0 is used for item preview
301 {281 {
302 $Obj = NULL;282 $Obj = NULL;
303 return $Obj;283 return $Obj;
304 }284 }
305285
306 if( isset( $this->cache[$obj_ID] ) )286 if( isset( $this->cache[$obj_ID] ) )
307 { // Already in cache, do nothing!287 {
288 // Already in cache, do nothing!
308 }289 }
309 elseif( isset( $this->shadow_cache[$obj_ID] ) )290 elseif( isset( $this->shadow_cache[$obj_ID] ) )
310 { // Already in shadow, recycle object:291 {
292 // Already in shadow, recycle object
311 $this->add( $this->shadow_cache[$obj_ID] );293 $this->add( $this->shadow_cache[$obj_ID] );
312 }294 }
313 else295 else
314 { // Not already cached, add new object:296 {
297 // Not already cached, add new object
315 $this->add( $this->new_obj( $db_row ) );298 $this->add( $this->new_obj( $db_row ) );
316 }299 }
317300
@@ -321,12 +304,12 @@
321304
322 /**305 /**
323 * Clear the cache **extensively**306 * Clear the cache **extensively**
324 *
325 */307 */
326 function clear( $keep_shadow = false )308 function clear( $keep_shadow = false )
327 {309 {
328 if( $keep_shadow )310 if( $keep_shadow )
329 { // Keep copy of cache in case we try to re instantiate previous object:311 {
312 // Keep copy of cache in case we try to re instantiate previous object
330 $this->shadow_cache = $this->cache;313 $this->shadow_cache = $this->cache;
331 }314 }
332 else315 else
@@ -341,33 +324,30 @@
341 }324 }
342325
343326
344 /**327 /**
345 * This provides a simple interface for looping over the contents of the Cache.328 * This provides a simple interface for looping over the contents of the Cache
346 *329 *
347 * This should only be used for basic enumeration.330 * This should only be used for basic enumeration. If you need complex filtering
348 * If you need complex filtering of the cache contents, you should probablt use a DataObjectList instead.331 * of the cache contents, you should probablt use a DataObjectList instead.
349 *332 *
350 * @see DataObject::get_next()333 * @see DataObject::get_next()
351 *
352 * @return DataObject334 * @return DataObject
353 */335 */
354 function & get_first()336 function & get_first()
355 {337 {
356 $this->load_all();338 $this->load_all();
357
358 $this->current_idx = -1;339 $this->current_idx = -1;
359 return $this->get_next();340 return $this->get_next();
360 }341 }
361342
362343
363 /**344 /**
364 * This provides a simple interface for looping over the contents of the Cache.345 * This provides a simple interface for looping over the contents of the Cache
365 *346 *
366 * This should only be used for basic enumeration.347 * This should only be used for basic enumeration. If you need complex filtering
367 * If you need complex filtering of the cache contents, you should probablt use a DataObjectList instead.348 * of the cache contents, you should probably use a DataObjectList instead.
368 *349 *
369 * @see DataObject::get_first()350 * @see DataObject::get_first()
370 *
371 * @return DataObject351 * @return DataObject
372 */352 */
373 function & get_next()353 function & get_next()
@@ -397,11 +377,11 @@
397 */377 */
398 function & get_by_ID( $req_ID, $halt_on_error = true, $halt_on_empty = true )378 function & get_by_ID( $req_ID, $halt_on_error = true, $halt_on_empty = true )
399 {379 {
400 global $DB, $Debuglog;380 global $DB;
401381
402 if( empty($req_ID) )382 if( empty( $req_ID ) )
403 {383 {
404 if($halt_on_empty)384 if( $halt_on_empty )
405 {385 {
406 debug_die( "Requested $this->objtype from $this->dbtablename without ID!" );386 debug_die( "Requested $this->objtype from $this->dbtablename without ID!" );
407 }387 }
@@ -409,41 +389,37 @@
409 return $r;389 return $r;
410 }390 }
411391
412 if( !empty( $this->cache[ $req_ID ] ) )392 if( ! empty( $this->cache[$req_ID] ) )
413 { // Already in cache393 {
414 // $Debuglog->add( "Accessing $this->objtype($req_ID) from cache", 'dataobjects' );394 // Already in cache
415 return $this->cache[ $req_ID ];395 return $this->cache[$req_ID];
416 }396 }
417 elseif( !$this->all_loaded )397 elseif( ! $this->all_loaded )
418 { // Not in cache, but not everything is loaded yet398 {
399 // Not in cache, but not everything is loaded yet
419 if( $this->load_all )400 if( $this->load_all )
420 { // It's ok to just load everything:401 {
402 // It's ok to just load everything
421 $this->load_all();403 $this->load_all();
422 }404 }
423 else405 else
424 { // Load just the requested object:406 {
425 $Debuglog->add( "Loading <strong>$this->objtype($req_ID)</strong> into cache", 'dataobjects' );407 // Load just the requested object
426 // Note: $req_ID MUST be an unsigned integer. This is how DataObject works.408 // Note: $req_ID MUST be an unsigned integer. This is how DataObject works.
427 $sql = "SELECT *409 $sql = "SELECT * FROM $this->dbtablename WHERE $this->dbIDname = $req_ID";
428 FROM $this->dbtablename
429 WHERE $this->dbIDname = $req_ID";
430 if( $row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_ID()' ) )410 if( $row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_ID()' ) )
431 {411 {
432 if( ! $this->instantiate( $row ) )412 if( ! $this->instantiate( $row ) )
433 {413 {
434 $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );414 // debuglog-add removed
435 }415 }
436 }416 }
437 else
438 {
439 $Debuglog->add( 'Could not get DataObject by ID. Query: '.$sql, 'dataobjects' );
440 }
441 }417 }
442 }418 }
443419
444 if( empty( $this->cache[ $req_ID ] ) )420 if( empty( $this->cache[$req_ID] ) )
445 { // Requested object does not exist421 {
446 // $Debuglog->add( 'failure', 'dataobjects' );422 // Requested object does not exist
447 if( $halt_on_error )423 if( $halt_on_error )
448 {424 {
449 debug_die( "Requested $this->objtype does not exist!" );425 debug_die( "Requested $this->objtype does not exist!" );
@@ -452,7 +428,7 @@
452 return $r;428 return $r;
453 }429 }
454430
455 return $this->cache[ $req_ID ];431 return $this->cache[$req_ID];
456 }432 }
457433
458434
@@ -468,45 +444,30 @@
468 */444 */
469 function & get_by_name( $req_name, $halt_on_error = true, $halt_on_empty = true )445 function & get_by_name( $req_name, $halt_on_error = true, $halt_on_empty = true )
470 {446 {
471 global $DB, $Debuglog;447 global $DB;
472448
473 if( empty( $this->name_field ) )449 if( empty( $this->name_field ) )
474 {450 {
475 debug_die( 'DataObjectCache::get_by_name() : No name field to query on' );451 debug_die( 'DataObjectCache::get_by_name() : No name field to query on' );
476 }452 }
477453
478 if( empty($req_name) )454 if( empty( $req_name ) )
479 {455 {
480 if($halt_on_empty) { debug_die( "Requested $this->objtype from $this->dbtablename without name!" ); }456 if( $halt_on_empty ) { debug_die( "Requested $this->objtype from $this->dbtablename without name!" ); }
481 $r = NULL;457 $r = NULL;
482 return $r;458 return $r;
483 }459 }
484460
485 // Load just the requested object:461 // Load just the requested object
486 $Debuglog->add( "Loading <strong>$this->objtype($req_name)</strong>", 'dataobjects' );462 $sql = "SELECT * FROM $this->dbtablename WHERE $this->name_field = ".$DB->quote( $req_name );
487 $sql = "SELECT *
488 FROM $this->dbtablename
489 WHERE $this->name_field = ".$DB->quote($req_name);
490463
491 if( $db_row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_name()' ) )464 if( $db_row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_name()' ) )
492 {465 {
493 $resolved_ID = $db_row->{$this->dbIDname};466 $resolved_ID = $db_row->{$this->dbIDname};
494 $Debuglog->add( 'success; ID = '.$resolved_ID, 'dataobjects' );
495 if( ! isset( $this->cache[$resolved_ID] ) )
496 { // Object is not already in cache:
497 $Debuglog->add( 'Adding to cache...', 'dataobjects' );
498 //$Obj = new $this->objtype( $row ); // COPY !!
499 //if( ! $this->add( $this->new_obj( $db_row ) ) )
500 if( ! $this->add( $this->new_obj( $db_row ) ) )
501 { // could not add
502 $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );
503 }
504 }
505 return $this->cache[$resolved_ID];467 return $this->cache[$resolved_ID];
506 }468 }
507 else469 else
508 {470 {
509 $Debuglog->add( 'Could not get DataObject by name.', 'dataobjects' );
510 if( $halt_on_error )471 if( $halt_on_error )
511 {472 {
512 debug_die( "Requested $this->objtype does not exist!" );473 debug_die( "Requested $this->objtype does not exist!" );
@@ -529,7 +490,7 @@
529490
530491
531 /**492 /**
532 * Delete an object from DB by ID.493 * Delete an object from DB by ID
533 *494 *
534 * @param integer ID of object to delete495 * @param integer ID of object to delete
535 * @return boolean496 * @return boolean
@@ -540,10 +501,8 @@
540 {501 {
541 // Delete from db502 // Delete from db
542 $this->cache[$req_ID]->dbdelete();503 $this->cache[$req_ID]->dbdelete();
543
544 // Remove from cache504 // Remove from cache
545 $this->remove_by_ID( $req_ID );505 $this->remove_by_ID( $req_ID );
546
547 return true;506 return true;
548 }507 }
549 else508 else
@@ -572,13 +531,16 @@
572 }531 }
573532
574 if( ! $this->all_loaded && $this->load_all )533 if( ! $this->all_loaded && $this->load_all )
575 { // We have not loaded all items so far, but we're allowed to.534 {
576 if ( empty( $ignore_IDs ) )535 // We have not loaded all items so far, but we're allowed to
577 { // just load all items536 if( empty( $ignore_IDs ) )
537 {
538 // just load all items
578 $this->load_all();539 $this->load_all();
579 }540 }
580 else541 else
581 { // only load those items not listed in $ignore_IDs542 {
543 // only load those items not listed in $ignore_IDs
582 $this->load_list( implode( ',', $ignore_IDs ), true );544 $this->load_list( implode( ',', $ignore_IDs ), true );
583 }545 }
584 }546 }
@@ -588,22 +550,23 @@
588 if( $allow_none )550 if( $allow_none )
589 {551 {
590 $r .= '<option value="'.$this->none_option_value.'"';552 $r .= '<option value="'.$this->none_option_value.'"';
591 if( empty($default) ) $r .= ' selected="selected"';553 if( empty( $default ) ) $r .= ' selected="selected"';
592 $r .= '>'.format_to_output($this->none_option_text).'</option>'."\n";554 $r .= '>'.format_to_output( $this->none_option_text ).'</option>'."\n";
593 }555 }
594556
595 foreach( $this->cache as $loop_Obj )557 foreach( $this->cache as $loop_Obj )
596 {558 {
597 if ( in_array( $loop_Obj->ID, $ignore_IDs ) )559 if( in_array( $loop_Obj->ID, $ignore_IDs ) )
598 { // Ignore this ID560 {
561 // Ignore this ID
599 continue;562 continue;
600 }563 }
601564
602 $r .= '<option value="'.$loop_Obj->ID.'"';565 $r .= '<option value="'.$loop_Obj->ID.'"';
603 if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';566 if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';
604 $r .= '>';567 $r .= '>';
605 $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' );568 $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' );
606 $r .= '</option>'."\n";569 $r .= '</option>'."\n";
607 }570 }
608571
609 return $r;572 return $r;
@@ -622,13 +585,16 @@
622 function get_option_array( $method = 'get_name', $ignore_IDs = array() )585 function get_option_array( $method = 'get_name', $ignore_IDs = array() )
623 {586 {
624 if( ! $this->all_loaded && $this->load_all )587 if( ! $this->all_loaded && $this->load_all )
625 { // We have not loaded all items so far, but we're allowed to.588 {
626 if ( empty( $ignore_IDs ) )589 // We have not loaded all items so far, but we're allowed to
627 { // just load all items590 if( empty( $ignore_IDs ) )
591 {
592 // just load all items
628 $this->load_all();593 $this->load_all();
629 }594 }
630 else595 else
631 { // only load those items not listed in $ignore_IDs596 {
597 // only load those items not listed in $ignore_IDs
632 $this->load_list( implode( ',', $ignore_IDs ), true );598 $this->load_list( implode( ',', $ignore_IDs ), true );
633 }599 }
634 }600 }
@@ -638,7 +604,8 @@
638 foreach( $this->cache as $loop_Obj )604 foreach( $this->cache as $loop_Obj )
639 {605 {
640 if( in_array( $loop_Obj->ID, $ignore_IDs ) )606 if( in_array( $loop_Obj->ID, $ignore_IDs ) )
641 { // Ignore this ID607 {
608 // Ignore this ID
642 continue;609 continue;
643 }610 }
644611
@@ -650,5 +617,4 @@
650617
651}618}
652619
653
654?>
655\ No newline at end of file620\ No newline at end of file
621?>
656622
=== modified file 'qp_inc/_core/model/dataobjects/_dataobjectlist.class.php'
--- qp_inc/_core/model/dataobjects/_dataobjectlist.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/dataobjects/_dataobjectlist.class.php 2013-03-20 18:13:29 +0000
@@ -1,66 +1,52 @@
1<?php1<?php
2/**2/**
3 * This file implements the abstract DataObjectList base class.3 * This file implements the DataObjectList class
4 *4 *
5 * This file is part of Quam Plures - {@link http://quamplures.net/}5 * This is typically an abstract class, useful only when derived. Holds DataObjects
6 * See also {@link https://launchpad.net/quam-plures}.6 * in an array and allows walking through...
7 *7 *
8 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}8 * @todo (1111) vars type 'foo' need useful/valid descriptions
9 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}9 * @author {@link http://wonderwinds.com/ Ed Bennett}
10 *10 * @author {@link http://fplanque.net/ Francois PLANQUE}
11 * {@internal License choice11 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
12 * - If you have received this file as part of a package, please find the license.txt file in12 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
13 * the same folder or the closest folder above for complete license terms.13 * @package core
14 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
15 * then you must choose one of the following licenses before using the file:
16 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
17 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
18 * }}
19 *
20 * {@internal Open Source relicensing agreement:
21 * }}
22 *
23 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
24 * @author fplanque: Francois PLANQUE
25 *
26 * @package pond
27 */14 */
28if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );15if(!defined('QP_MAIN_INIT')) die('fail');
29
30load_class('_core/ui/results/_results.class.php');
3116
32/**17/**
33 * Data Object List Base Class18 * DataObjectList class
34 *19 *
35 * This is typically an abstract class, useful only when derived.20 * @package core
36 * Holds DataObjects in an array and allows walking through...
37 *
38 * @version beta
39 * @abstract
40 *
41 * @package pond
42 */21 */
43class DataObjectList extends Results22class DataObjectList extends Results
44{23{
45
46 /**24 /**
47 * The following should probably be obsoleted by Results::Cache25 * The following should probably be obsoleted by Results::Cache
48 */26 * @var foo
49 var $dbtablename;27 */
28 var $dbtablename;
29 /**
30 * FIX THIS
31 * @var foo
32 */
50 var $dbprefix;33 var $dbprefix;
34 /**
35 * FIX THIS
36 * @var foo
37 */
51 var $dbIDname;38 var $dbIDname;
52
53 /**39 /**
54 * Class name of objects handled in this list40 * Class name of objects handled in this list
41 * @var foo
55 */42 */
56 var $objType;43 var $objType;
57
58 /**44 /**
59 * Object array45 * Object array
46 * @var foo
60 */47 */
61 var $Obj = array();48 var $Obj = array();
6249
63
64 /**50 /**
65 * Constructor51 * Constructor
66 *52 *
@@ -75,8 +61,14 @@
75 * @param string prefix to differentiate page/order params when multiple Results appear one same page61 * @param string prefix to differentiate page/order params when multiple Results appear one same page
76 * @param string default ordering of columns (special syntax)62 * @param string default ordering of columns (special syntax)
77 */63 */
78 function DataObjectList( $tablename, $prefix = '', $dbIDname = 'ID', $objType = 'Item', $sql = NULL,64 function DataObjectList(
79 $limit = 20, $param_prefix = '', $default_order = NULL )65 $tablename, $prefix = '',
66 $dbIDname = 'ID',
67 $objType = 'Item',
68 $sql = NULL,
69 $limit = 20,
70 $param_prefix = '',
71 $default_order = NULL )
80 {72 {
81 $this->dbtablename = $tablename;73 $this->dbtablename = $tablename;
82 $this->dbprefix = $prefix;74 $this->dbprefix = $prefix;
@@ -84,12 +76,14 @@
84 $this->objType = $objType;76 $this->objType = $objType;
8577
86 if( !is_null( $sql ) )78 if( !is_null( $sql ) )
87 { // We have an SQL query to execute:79 {
80 // We have an SQL query to execute
88 parent::Results( $sql, $param_prefix, $default_order, $limit );81 parent::Results( $sql, $param_prefix, $default_order, $limit );
89 }82 }
90 else83 else
91 { // TODO: do we want to autogenerate a query here???84 {
92 // Temporary...85 // Temporary...
86 // @todo (0000) do we want to autogenerate a query here???
93 parent::Results( $sql, $param_prefix, $default_order, $limit );87 parent::Results( $sql, $param_prefix, $default_order, $limit );
94 }88 }
95 }89 }
@@ -103,7 +97,8 @@
103 function & get_next()97 function & get_next()
104 {98 {
105 if( $this->current_idx >= $this->result_num_rows )99 if( $this->current_idx >= $this->result_num_rows )
106 { // No more comment in list100 {
101 // No more comment in list
107 $r = false;102 $r = false;
108 return $r;103 return $r;
109 }104 }
@@ -112,4 +107,4 @@
112107
113}108}
114109
115?>
116\ No newline at end of file110\ No newline at end of file
111?>
117112
=== modified file 'qp_inc/_core/model/dataobjects/_dataobjectlist2.class.php'
--- qp_inc/_core/model/dataobjects/_dataobjectlist2.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/dataobjects/_dataobjectlist2.class.php 2013-03-20 18:13:29 +0000
@@ -1,53 +1,34 @@
1<?php1<?php
2/**2/**
3 * This file implements the abstract DataObjectList2 base class.3 * This file implements the abstract FilteredResults class
4 *4 *
5 * This file is part of Quam Plures - {@link http://quamplures.net/}5 * @todo (1111) vars type 'foo' need useful/valid descriptions
6 * See also {@link https://launchpad.net/quam-plures}.6 * @author {@link http://wonderwinds.com/ Ed Bennett}
7 *7 * @author {@link http://fplanque.net/ Francois PLANQUE}
8 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}8 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
9 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}9 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
10 *10 * @package core
11 * {@internal License choice
12 * - If you have received this file as part of a package, please find the license.txt file in
13 * the same folder or the closest folder above for complete license terms.
14 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
15 * then you must choose one of the following licenses before using the file:
16 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
17 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
18 * }}
19 *
20 * {@internal Open Source relicensing agreement:
21 * }}
22 *
23 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
24 * @author fplanque: Francois PLANQUE
25 *
26 * @package pond
27 */11 */
28if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );12if(!defined('QP_MAIN_INIT')) die('fail');
29
30load_class('_core/ui/results/_results.class.php');
31
3213
33/**14/**
34 * FilteredResults > Results15 * FilteredResults class
35 *16 *
36 * @package pond17 * @package core
37 */18 */
38class FilteredResults extends Results19class FilteredResults extends Results
39{20{
40 /**21 /**
41 * Default filter set (used if no specific params are passed)22 * Default filter set (used if no specific params are passed)
23 * @var foo
42 */24 */
43 var $default_filters = array();25 var $default_filters = array();
44
45 /**26 /**
46 * Current filter set (depending on user input)27 * Current filter set (depending on user input)
28 * @var foo
47 */29 */
48 var $filters = array();30 var $filters = array();
4931
50
51 /**32 /**
52 * Check if the Result set is filtered or not33 * Check if the Result set is filtered or not
53 */34 */
@@ -57,7 +38,6 @@
57 {38 {
58 return false;39 return false;
59 }40 }
60
61 return ( $this->filters != $this->default_filters );41 return ( $this->filters != $this->default_filters );
62 }42 }
6343
@@ -67,7 +47,7 @@
67 */47 */
68 function get_active_filter( $key )48 function get_active_filter( $key )
69 {49 {
70 if( isset($this->filters[$key]) )50 if( isset( $this->filters[$key] ) )
71 {51 {
72 return $this->filters[$key];52 return $this->filters[$key];
73 }53 }
@@ -76,7 +56,7 @@
76 }56 }
7757
7858
79 /**59 /**
80 * Get every active filter that is not the same as the defaults60 * Get every active filter that is not the same as the defaults
81 */61 */
82 function get_active_filters()62 function get_active_filters()
@@ -85,10 +65,12 @@
8565
86 foreach( $this->default_filters as $key => $value )66 foreach( $this->default_filters as $key => $value )
87 {67 {
88 if( !isset( $this->filters[$key] ) )68 if( ! isset( $this->filters[$key] ) )
89 { // Some value has not been copied over from defaults to active or specifically set:69 {
90 if( !is_null($value)) // Note: NULL value are not copied over. that's normal.70 // Some value has not been copied over from defaults to active or specifically set:
91 { // A NON NULL value is missing71 if( ! is_null( $value ) ) // Note: NULL value are not copied over. that's normal.
72 {
73 // A NON NULL value is missing
92 $r[] = $key;74 $r[] = $key;
93 }75 }
94 }76 }
@@ -101,17 +83,19 @@
101 }83 }
10284
10385
104 /**86 /**
105 * Show every active filter that is not the same as the defaults87 * Show every active filter that is not the same as the defaults
106 */88 */
107 function dump_active_filters()89 function dump_active_filters()
108 {90 {
109 foreach( $this->default_filters as $key => $value )91 foreach( $this->default_filters as $key => $value )
110 {92 {
111 if( !isset( $this->filters[$key] ) )93 if( ! isset( $this->filters[$key] ) )
112 { // SOme value has not been copied over from defaults to active or specifically set:94 {
113 if( !is_null($value)) // Note: NULL value ar enot copied over. that's normal.95 // Some value has not been copied over from defaults to active or specifically set
114 { // A NON NULL value is missing96 if( ! is_null( $value ) ) // Note: NULL value are not copied over. that's normal.
97 {
98 // A NON NULL value is missing
115 pre_dump( 'no active value for default '.$key );99 pre_dump( 'no active value for default '.$key );
116 }100 }
117 }101 }
@@ -125,60 +109,51 @@
125}109}
126110
127111
128
129/**112/**
130 * Data Object List Base Class 2113 * Data Object List Base Class 2
131 *114 *
132 * This is typically an abstract class, useful only when derived.115 * This is typically an abstract class, useful only when derived. Holds DataObjects
133 * Holds DataObjects in an array and allows walking through...116 * in an array and allows walking through... This SECOND implementation will deprecate
134 *117 * the first one when finished.
135 * This SECOND implementation will deprecate the first one when finished.118 *
136 *119 * @package core
137 * @version beta
138 * @abstract
139 *
140 * @package pond
141 */120 */
142class DataObjectList2 extends FilteredResults121class DataObjectList2 extends FilteredResults
143{122{
144
145
146 /**123 /**
147 * Constructor124 * Constructor
148 *125 *
149 * If provided, executes SQL query via parent Results object126 * If provided, executes SQL query via parent Results object
150 *127 *
151 * @param DataObjectCache128 * @param DataObjectCache
152 * @param integer number of lines displayed on one screen (null for default [20])129 * @param integer number of lines displayed on one screen (null for default [20] )
153 * @param string prefix to differentiate page/order params when multiple Results appear one same page130 * @param string prefix to differentiate page/order params when multiple Results appear one same page
154 * @param string default ordering of columns (special syntax)131 * @param string default ordering of columns (special syntax)
155 */132 */
156 function DataObjectList2( & $Cache, $limit = null, $param_prefix = '', $default_order = NULL )133 function DataObjectList2( & $Cache, $limit = null, $param_prefix = '', $default_order = NULL )
157 {134 {
158 // WARNING: we are not passing any SQL query to the Results object135 // WARNING: we are not passing any SQL query to the Results object
159 // This will make the Results object behave a little bit differently than usual:136 // This will make the Results object behave a little bit differently than usual
160 parent::Results( NULL, $param_prefix, $default_order, $limit, NULL, false );137 parent::Results( NULL, $param_prefix, $default_order, $limit, NULL, false );
161
162 // The list objects will also be cached in this cache.138 // The list objects will also be cached in this cache.
163 // Tje Cache object may also be useful to get table information for the Items.139 // The Cache object may also be useful to get table information for the Items
164 $this->Cache = & $Cache;140 $this->Cache = & $Cache;
165
166 // Colum used for IDs141 // Colum used for IDs
167 $this->ID_col = $Cache->dbIDname;142 $this->ID_col = $Cache->dbIDname;
168 }143 }
169144
170145
171/**146 /**
172 * dummy docblock makes error-free autodocs147 * dummy docblock
173 */148 */
174 function & get_row_by_idx( $idx )149 function & get_row_by_idx( $idx )
175 {150 {
176 return $this->rows[ $idx ];151 return $this->rows[$idx];
177 }152 }
178153
179154
180 /**155 /**
181 * Instantiate an object for requested row and cache it:156 * Instantiate an object for requested row and cache it
182 */157 */
183 function & get_by_idx( $idx )158 function & get_by_idx( $idx )
184 {159 {
@@ -192,13 +167,14 @@
192 function & get_next()167 function & get_next()
193 {168 {
194 if( $this->current_idx >= $this->result_num_rows )169 if( $this->current_idx >= $this->result_num_rows )
195 { // No more object in list170 {
171 // No more object in list
196 $this->current_Obj = NULL;172 $this->current_Obj = NULL;
197 $r = false; // TODO: try with NULL173 $r = false;
198 return $r;174 return $r;
199 }175 }
200176
201 // We also keep a local ref in case we want to use it for display:177 // We also keep a local ref in case we want to use it for display
202 $this->current_Obj = & $this->get_by_idx( $this->current_idx );178 $this->current_Obj = & $this->get_by_idx( $this->current_idx );
203 $this->next_idx();179 $this->next_idx();
204180
@@ -210,7 +186,6 @@
210 * Display a global title matching filter params186 * Display a global title matching filter params
211 *187 *
212 * @todo implement $order188 * @todo implement $order
213 *
214 * @param string prefix to display if a title is generated189 * @param string prefix to display if a title is generated
215 * @param string suffix to display if a title is generated190 * @param string suffix to display if a title is generated
216 * @param string glue to use if multiple title elements are generated191 * @param string glue to use if multiple title elements are generated
@@ -221,12 +196,12 @@
221 {196 {
222 $title_array = $this->get_filter_titles();197 $title_array = $this->get_filter_titles();
223198
224 if( empty( $title_array ) )199 if( empty( $title_array ) )
225 {200 {
226 return '';201 return '';
227 }202 }
228203
229 // We have something to display:204 // We have something to display
230 $r = implode( $glue, $title_array );205 $r = implode( $glue, $title_array );
231 $r = $prefix.format_to_output( $r, $format ).$suffix;206 $r = $prefix.format_to_output( $r, $format ).$suffix;
232 return $r;207 return $r;
@@ -245,7 +220,7 @@
245220
246 $DB->begin();221 $DB->begin();
247222
248 if( ($obj = & $this->Cache->get_by_ID( $id )) === false )223 if( ( $obj = & $this->Cache->get_by_ID( $id ) ) === false )
249 {224 {
250 $Messages->head = T_('Cannot edit entry!');225 $Messages->head = T_('Cannot edit entry!');
251 $Messages->add( T_('Requested entry does not exist any longer.'), 'error' );226 $Messages->add( T_('Requested entry does not exist any longer.'), 'error' );
@@ -256,24 +231,21 @@
256231
257 // Get the ID of the inferior element which his order is the nearest232 // Get the ID of the inferior element which his order is the nearest
258 $rows = $DB->get_results( 'SELECT '.$this->Cache->dbIDname233 $rows = $DB->get_results( 'SELECT '.$this->Cache->dbIDname
259 .' FROM '.$this->Cache->dbtablename234 .' FROM '.$this->Cache->dbtablename
260 .' WHERE '.$this->Cache->dbprefix.'order < '.$order235 .' WHERE '.$this->Cache->dbprefix.'order < '.$order
261 .' ORDER BY '.$this->Cache->dbprefix.'order DESC236 .' ORDER BY '.$this->Cache->dbprefix.'order DESC
262 LIMIT 0,1' );237 LIMIT 0, 1' );
263238
264 if( count( $rows ) )239 if( count( $rows ) )
265 {240 {
266 // instantiate the inferior element241 // instantiate the inferior element
267 $obj_inf = & $this->Cache->get_by_ID( $rows[0]->{$this->Cache->dbIDname} );242 $obj_inf = & $this->Cache->get_by_ID( $rows[0]->{$this->Cache->dbIDname} );
268243 // Update element order
269 // Update element order
270 $obj->set( 'order', $obj_inf->order );244 $obj->set( 'order', $obj_inf->order );
271 $obj->dbupdate();245 $obj->dbupdate();
272
273 // Update inferior element order246 // Update inferior element order
274 $obj_inf->set( 'order', $order );247 $obj_inf->set( 'order', $order );
275 $obj_inf->dbupdate();248 $obj_inf->dbupdate();
276
277 // EXPERIMENTAL FOR FADEOUT RESULT249 // EXPERIMENTAL FOR FADEOUT RESULT
278 $result_fadeout[$this->Cache->dbIDname][] = $id;250 $result_fadeout[$this->Cache->dbIDname][] = $id;
279 $result_fadeout[$this->Cache->dbIDname][] = $obj_inf->ID;251 $result_fadeout[$this->Cache->dbIDname][] = $obj_inf->ID;
@@ -294,11 +266,13 @@
294 */266 */
295 function move_down( $id )267 function move_down( $id )
296 {268 {
297 global $DB, $Messages, $result_fadeout;269 global $DB;
270 global $Messages;
271 global $result_fadeout;
298272
299 $DB->begin();273 $DB->begin();
300274
301 if( ($obj = & $this->Cache->get_by_ID( $id )) === false )275 if( ( $obj = & $this->Cache->get_by_ID( $id ) ) === false )
302 {276 {
303 $Messages->head = T_('Cannot edit entry!');277 $Messages->head = T_('Cannot edit entry!');
304 $Messages->add( T_('Requested entry does not exist any longer.'), 'error' );278 $Messages->add( T_('Requested entry does not exist any longer.'), 'error' );
@@ -309,24 +283,21 @@
309283
310 // Get the ID of the inferior element which his order is the nearest284 // Get the ID of the inferior element which his order is the nearest
311 $rows = $DB->get_results( 'SELECT '.$this->Cache->dbIDname285 $rows = $DB->get_results( 'SELECT '.$this->Cache->dbIDname
312 .' FROM '.$this->Cache->dbtablename286 .' FROM '.$this->Cache->dbtablename
313 .' WHERE '.$this->Cache->dbprefix.'order > '.$order287 .' WHERE '.$this->Cache->dbprefix.'order > '.$order
314 .' ORDER BY '.$this->Cache->dbprefix.'order ASC288 .' ORDER BY '.$this->Cache->dbprefix.'order ASC
315 LIMIT 0,1' );289 LIMIT 0, 1' );
316290
317 if( count( $rows ) )291 if( count( $rows ) )
318 {292 {
319 // instantiate the inferior element293 // instantiate the inferior element
320 $obj_sup = & $this->Cache->get_by_ID( $rows[0]->{$this->Cache->dbIDname} );294 $obj_sup = & $this->Cache->get_by_ID( $rows[0]->{$this->Cache->dbIDname} );
321295 // Update element order
322 // Update element order
323 $obj->set( 'order', $obj_sup->order );296 $obj->set( 'order', $obj_sup->order );
324 $obj->dbupdate();297 $obj->dbupdate();
325
326 // Update inferior element order298 // Update inferior element order
327 $obj_sup->set( 'order', $order );299 $obj_sup->set( 'order', $order );
328 $obj_sup->dbupdate();300 $obj_sup->dbupdate();
329
330 // EXPERIMENTAL FOR FADEOUT RESULT301 // EXPERIMENTAL FOR FADEOUT RESULT
331 $result_fadeout[$this->Cache->dbIDname][] = $id;302 $result_fadeout[$this->Cache->dbIDname][] = $id;
332 $result_fadeout[$this->Cache->dbIDname][] = $obj_sup->ID;303 $result_fadeout[$this->Cache->dbIDname][] = $obj_sup->ID;
@@ -339,4 +310,4 @@
339 }310 }
340}311}
341312
342?>
343\ No newline at end of file313\ No newline at end of file
314?>
344315
=== modified file 'qp_inc/_core/model/db/_db.class.php'
--- qp_inc/_core/model/db/_db.class.php 2010-12-31 12:12:03 +0000
+++ qp_inc/_core/model/db/_db.class.php 2013-03-20 18:13:29 +0000
@@ -1,80 +1,55 @@
1<?php1<?php
2/**2/**
3 * This file implements the DB class.3 * This file implements the DB base class
4 *4 *
5 * Based on ezSQL - Class to make it very easy to deal with MySQL database connections.
6 * b2evo Additions:
7 * - nested transactions
8 * - symbolic table names
9 * - query log
10 * - get_list
11 * - dynamic extension loading
12 * - Debug features (EXPLAIN...)
13 * and more...
14 *
15 * This file is part of the Quam Plures project - {@link http://quamplures.net/}.
16 * See also {@link https://launchpad.net/quam-plures}.
17 *
18 * @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
19 * @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}.
20 * Parts of this file are copyright (c)2004 by Justin Vincent - {@link http://php.justinvincent.com}
21 * Parts of this file are copyright (c)2004-2005 by Daniel HAHLER - {@link http://thequod.de/contact}.
22 *
23 * {@internal License choice
24 * - If you have received this file as part of a package, please find the license.txt file in
25 * the same folder or the closest folder above for complete license terms.
26 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
27 * then you must choose one of the following licenses before using the file:
28 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
29 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
30 * }}
31 *
32 * {@internal Origin:
33 * This file is based on the following package (excerpt from ezSQL's readme.txt):5 * This file is based on the following package (excerpt from ezSQL's readme.txt):
34 * =======================================================================6 * =======================================================================
35 * Author: Justin Vincent (justin@visunet.ie)7 * Author: Justin Vincent (justin@visunet.ie)
36 * Web: http://php.justinvincent.com8 * Web: http://php.justinvincent.com
37 * Name: ezSQL9 * Name: ezSQL
38 * Desc: Class to make it very easy to deal with database connections.10 * Desc: Class to make it very easy to deal with database connections.
39 * License: FREE / Donation (LGPL - You may do what you like with ezSQL - no exceptions.)11 * License: FREE / Donation (LGPL - You may do what you like with ezSQL - no exceptions.)
40 * =======================================================================12 * =======================================================================
41 * A $10 donation has been made to Justin VINCENT on behalf of the b2evolution team.13 * A $10 donation has been made to Justin VINCENT on behalf of the b2evolution team.
42 * The package has been relicensed as GPL based on14 * The package has been relicensed as GPL based on
43 * "You may do what you like with ezSQL - no exceptions."15 * "You may do what you like with ezSQL - no exceptions."
44 * 2004-10-14 (email): Justin VINCENT grants Francois PLANQUE the right to relicense16 * 2004-10-14 (email): Justin VINCENT grants Francois PLANQUE the right to relicense
45 * this modified class under other licenses. "Just include a link to where you got it from."17 * this modified class under other licenses. "Just include a link to where you got
46 * }}18 * it from."
47 *19 *
48 * {@internal Open Source relicensing agreement:20 * @todo (1111) vars type 'foo' need useful/valid descriptions
49 * Daniel HAHLER grants Francois PLANQUE the right to license21 * @todo (0000) transaction support
50 * Daniel HAHLER's contributions to this file and the b2evolution project22 * @author {@link http://wonderwinds.com/ Ed Bennett}
51 * under any OSI approved OSS license (http://www.opensource.org/licenses/).23 * @author {@link http://daniel.hahler.de/ Daniel HAHLER}
52 * }}24 * @author {@link http://fplanque.net/ Francois PLANQUE}
53 *25 * @author {@link http://php.justinvincent.com Justin VINCENT}
54 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}26 * @copyright (c) 2009 by {@link http://quamplures.net/ the Quam Plures project}
55 * @author blueyed: Daniel HAHLER27 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License v3
56 * @author fplanque: Francois PLANQUE28 * @package core
57 * @author Justin VINCENT
58 *
59 * @todo transaction support
60 *
61 * @package pond
62 */29 */
63if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );30if(!defined('QP_MAIN_INIT')) die('fail');
6431
65/**32/**
66 * ezSQL Constants33 * ezSQL Constants
67 */34 */
68define( 'EZSQL_VERSION', '1.25' );35define( 'EZSQL_VERSION', '1.25' );
36/**
37 * ezSQL Constants
38 */
69define( 'OBJECT', 'OBJECT', true );39define( 'OBJECT', 'OBJECT', true );
40/**
41 * ezSQL Constants
42 */
70define( 'ARRAY_A', 'ARRAY_A', true);43define( 'ARRAY_A', 'ARRAY_A', true);
44/**
45 * ezSQL Constants
46 */
71define( 'ARRAY_N', 'ARRAY_N', true);47define( 'ARRAY_N', 'ARRAY_N', true);
7248
73
74/**49/**
75 * The Main Class50 * DB base class
76 *51 *
77 * @package pond52 * @package core
78 */53 */
79class DB54class DB
80{55{
@@ -94,7 +69,7 @@
94 */69 */
95 var $error = false;70 var $error = false;
96 /**71 /**
97 * Number of done queries.72 * Number of done queries
98 * @var integer73 * @var integer
99 */74 */
100 var $num_queries = 0;75 var $num_queries = 0;
@@ -108,168 +83,150 @@
108 * @var string83 * @var string
109 */84 */
110 var $last_error = '';85 var $last_error = '';
111
112 /**86 /**
113 * Last insert ID87 * Last insert ID
114 * @var integer88 * @var integer
115 */89 */
116 var $insert_id = 0;90 var $insert_id = 0;
117
118 /**91 /**
119 * Last query's resource92 * Last query's resource
120 * @access protected
121 * @var resource93 * @var resource
122 */94 */
123 var $result;95 var $result;
124
125 /**96 /**
126 * Last result's rows97 * Last result's rows
127 * @var array98 * @var array
128 */99 */
129 var $last_result;100 var $last_result;
130
131 /**101 /**
132 * Number of rows in result set (after a select)102 * Number of rows in result set (after a select)
103 * @var foo
133 */104 */
134 var $num_rows = 0;105 var $num_rows = 0;
135
136 /**106 /**
137 * Number of rows affected by insert, delete, update or replace107 * Number of rows affected by insert, delete, update or replace
108 * @var foo
138 */109 */
139 var $rows_affected = 0;110 var $rows_affected = 0;
140
141 /**111 /**
142 * Aliases that will be replaced in queries:112 * Aliases that will be replaced in queries
113 * @var foo
143 */114 */
144 var $dbaliases = array();115 var $dbaliases = array();
145 /**116 /**
146 * Strings that will replace the aliases in queries:117 * Strings that will replace the aliases in queries
118 * @var foo
147 */119 */
148 var $dbreplaces = array();120 var $dbreplaces = array();
149
150 /**121 /**
151 * CREATE TABLE options.122 * CREATE TABLE options
152 *123 *
153 * This gets appended to every "CREATE TABLE" query.124 * This gets appended to every "CREATE TABLE" query. Edit those if you have control over your MySQL
154 *125 * server and want a more professional database than what is commonly offered by popular hosting providers.
155 * Edit those if you have control over you MySQL server and want a more professional126 *
156 * database than what is commonly offered by popular hosting providers.
157 *
158 * @todo dh> If the query itself uses already e.g. "CHARACTER SET latin1" it should not get overridden..
159 * @var string127 * @var string
160 */128 */
161 var $table_options = '';129 var $table_options = '';
162
163 /**130 /**
164 * Use transactions in DB?131 * Use transactions in DB?
165 *132 *
166 * You need to use InnoDB in order to enable this. See the {@link $app_db_config "table_options" key}.133 * You need to use InnoDB in order to enable this. See the {@link $app_db_config
134 * "table_options" key}.
135 *
136 * @var foo
167 */137 */
168 var $use_transactions = false;138 var $use_transactions = false;
169
170 /**139 /**
171 * How many transactions are currently nested?140 * How many transactions are currently nested?
141 * @var foo
172 */142 */
173 var $transaction_nesting_level = 0;143 var $transaction_nesting_level = 0;
174
175 /**144 /**
176 * Rememeber if we have to rollback at the end of a nested transaction construct145 * Rememeber if we have to rollback at the end of a nested transaction construct
146 * @var foo
177 */147 */
178 var $rollback_nested_transaction = false;148 var $rollback_nested_transaction = false;
179
180 /**149 /**
181 * MySQL Database handle150 * MySQL Database handle
182 * @var object151 * @var object
183 */152 */
184 var $dbhandle;153 var $dbhandle;
185
186 /**154 /**
187 * Database username155 * Database username
188 * @var string156 * @var string
189 */157 */
190 var $dbuser;158 var $dbuser;
191
192 /**159 /**
193 * Database username's password160 * Database username's password
194 * @var string161 * @var string
195 */162 */
196 var $dbpassword;163 var $dbpassword;
197
198 /**164 /**
199 * Database name165 * Database name
200 * @var string166 * @var string
201 * @see select()
202 */167 */
203 var $dbname;168 var $dbname;
204
205 /**169 /**
206 * Database hostname170 * Database hostname
207 * @var string171 * @var string
208 */172 */
209 var $dbhost = 'localhost';173 var $dbhost = 'localhost';
210
211 /**174 /**
212 * Current connection charset175 * Current connection charset
213 * @var string176 * @var string
214 * @see DB::set_connection_charset()177 * @see DB::set_connection_charset()
215 */178 */
216 var $connection_charset;179 var $connection_charset;
217
218
219 // DEBUG:
220
221 /**180 /**
222 * Do we want to log queries?181 * Do we want to log queries?
223 * If null, it gets set according to {@link $debug}.182 *
224 * A subclass may set it by default (e.g. DbUnitTestCase_DB).183 * If null, it gets set according to {@link $debug}. A subclass may set it by
184 * default (e.g. DbUnitTestCase_DB).
185 *
225 * @var boolean186 * @var boolean
226 */187 */
227 var $log_queries;188 var $log_queries;
228
229 /**189 /**
230 * Log of queries:190 * Log of queries
231 * @var array191 * @var array
232 */192 */
233 var $queries = array();193 var $queries = array();
234
235 /**194 /**
236 * Do we want to explain joins?195 * Do we want to explain joins?
196 *
237 * This requires {@link DB::$log_queries} to be true.197 * This requires {@link DB::$log_queries} to be true.
238 *198 *
239 * @todo fp> we'd probably want to group all the advanced debug vars under a single setting now. We might even auto enable it when $debug=2. (And we might actually want to include a $debug="cookie" mode for easy switching with bookmarks or a bookmarklet)199 * @todo (0000) fp> we'd probably want to group all the advanced debug vars under a single setting now. We might even auto enable it when $debug=2. (And we might actually want to include a $debug="cookie" mode for easy switching with bookmarks or a bookmarklet)
240 *
241 * @var boolean200 * @var boolean
242 */201 */
243 var $debug_explain_joins = false;202 var $debug_explain_joins = false;
244
245 /**203 /**
246 * Do we want to output a function backtrace for every query?204 * Do we want to output a function backtrace for every query?
205 *
247 * Number of stack entries to show (from last to first) (Default: 0); true means 'all'.206 * Number of stack entries to show (from last to first) (Default: 0); true means 'all'.
248 *
249 * This requires {@link DB::$log_queries} to be true.207 * This requires {@link DB::$log_queries} to be true.
250 *208 *
251 * @var integer209 * @var integer
252 */210 */
253 var $debug_dump_function_trace_for_queries = 0;211 var $debug_dump_function_trace_for_queries = 0;
254
255 /**212 /**
256 * Number of rows we want to dump in debug output (0 disables it)213 * Number of rows we want to dump in debug output (0 disables it)
214 *
257 * This requires {@link DB::$log_queries} to be true.215 * This requires {@link DB::$log_queries} to be true.
216 *
258 * @var integer217 * @var integer
259 */218 */
260 var $debug_dump_rows = 0;219 var $debug_dump_rows = 0;
261
262 /**220 /**
263 * Time in seconds that is considered a fast query (green).221 * Time in seconds that is considered a fast query (green)
222 * @see dump_queries()
264 * @var float223 * @var float
265 * @see dump_queries()
266 */224 */
267 var $query_duration_fast = 0.05;225 var $query_duration_fast = 0.05;
268
269 /**226 /**
270 * Time in seconds that is considered a slow query (red).227 * Time in seconds that is considered a slow query (red)
228 * @see dump_queries()
271 * @var float229 * @var float
272 * @see dump_queries()
273 */230 */
274 var $query_duration_slow = 0.3;231 var $query_duration_slow = 0.3;
275232
@@ -279,32 +236,36 @@
279 *236 *
280 * Connects to the server and selects a database.237 * Connects to the server and selects a database.
281 *238 *
239 * Mandatory parameters:
240 * - 'user': username to connect with
241 * - 'password': password to connect with OR
242 * - 'handle': a MySQL Database handle (from a previous {@link mysql_connect()})
243 *
244 * Optional parameters:
245 * - 'name': the name of the default database, see {@link DB::select()}
246 * - 'host': host of the database; Default: 'localhost'
247 * - 'show_errors': Display SQL errors? (true/false); Default: don't change member
248 * default ({@link $show_errors})
249 * - 'halt_on_error': Halt on error? (true/false); Default: don't change member
250 * default ({@link $halt_on_error})
251 * - 'table_options': sets {@link $table_options}
252 * - 'use_transactions': sets {@link $use_transactions}
253 * - 'aliases': Aliases for tables (array( alias => table name )); Default: no aliases.
254 * - 'new_link': create a new link to the DB, even if there was a mysql_connect() with
255 * the same params before. (requires PHP 4.2)
256 * - 'client_flags': optional settings like compression or SSL encryption. See
257 * {@link http://www.php.net/manual/en/ref.mysql.php#mysql.client-flags}.
258 *
282 * @param array An array of parameters.259 * @param array An array of parameters.
283 * Manadatory:
284 * - 'user': username to connect with
285 * - 'password': password to connect with
286 * OR
287 * - 'handle': a MySQL Database handle (from a previous {@link mysql_connect()})
288 * Optional:
289 * - 'name': the name of the default database, see {@link DB::select()}
290 * - 'host': host of the database; Default: 'localhost'
291 * - 'show_errors': Display SQL errors? (true/false); Default: don't change member default ({@link $show_errors})
292 * - 'halt_on_error': Halt on error? (true/false); Default: don't change member default ({@link $halt_on_error})
293 * - 'table_options': sets {@link $table_options}
294 * - 'use_transactions': sets {@link $use_transactions}
295 * - 'aliases': Aliases for tables (array( alias => table name )); Default: no aliases.
296 * - 'new_link': create a new link to the DB, even if there was a mysql_connect() with
297 * the same params before. (requires PHP 4.2)
298 * - 'client_flags': optional settings like compression or SSL encryption. See {@link http://www.php.net/manual/en/ref.mysql.php#mysql.client-flags}.
299 * (requires PHP 4.3)
300 */260 */
301 function DB( $params )261 function DB( $params )
302 {262 {
303 global $debug;263 global $debug;
304264
305 // Mandatory parameters:265 // Mandatory parameters
306 if( isset( $params['handle'] ) )266 if( isset( $params['handle'] ) )
307 { // DB-Link provided:267 {
268 // DB-Link provided
308 $this->dbhandle = $params['handle'];269 $this->dbhandle = $params['handle'];
309 }270 }
310 else271 else
@@ -313,35 +274,73 @@
313 $this->dbpassword = $params['password'];274 $this->dbpassword = $params['password'];
314 }275 }
315276
316 // Optional parameters (Allow overriding through $params):277 // Optional parameters (Allow overriding through $params)
317 if( isset($params['name']) ) $this->dbname = $params['name'];278 if( isset( $params['name'] ) )
318 if( isset($params['host']) ) $this->dbhost = $params['host'];279 {
319 if( isset($params['show_errors']) ) $this->show_errors = $params['show_errors'];280 $this->dbname = $params['name'];
320 if( isset($params['halt_on_error']) ) $this->halt_on_error = $params['halt_on_error'];281 }
321 if( isset($params['table_options']) ) $this->table_options = $params['table_options'];282
322 if( isset($params['use_transactions']) ) $this->use_transactions = $params['use_transactions'];283 if( isset( $params['host'] ) )
323 if( isset($params['debug_dump_rows']) ) $this->debug_dump_rows = $params['debug_dump_rows']; // Nb of rows to dump284 {
324 if( isset($params['debug_explain_joins']) ) $this->debug_explain_joins = $params['debug_explain_joins'];285 $this->dbhost = $params['host'];
325 if( isset($params['debug_dump_function_trace_for_queries']) ) $this->debug_dump_function_trace_for_queries = $params['debug_dump_function_trace_for_queries'];286 }
326287
327 if( isset($debug) && ! isset($this->log_queries) )288 if( isset( $params['show_errors'] ) )
328 { // $log_queries follows $debug and respects subclasses, which may define it:289 {
290 $this->show_errors = $params['show_errors'];
291 }
292
293 if( isset( $params['halt_on_error'] ) )
294 {
295 $this->halt_on_error = $params['halt_on_error'];
296 }
297
298 if( isset( $params['table_options'] ) )
299 {
300 $this->table_options = $params['table_options'];
301 }
302
303 if( isset( $params['use_transactions'] ) )
304 {
305 $this->use_transactions = $params['use_transactions'];
306 }
307
308 if( isset( $params['debug_dump_rows'] ) )
309 {
310 $this->debug_dump_rows = $params['debug_dump_rows']; // Nb of rows to dump
311 }
312
313 if( isset( $params['debug_explain_joins'] ) )
314 {
315 $this->debug_explain_joins = $params['debug_explain_joins'];
316 }
317
318 if( isset( $params['debug_dump_function_trace_for_queries'] ) )
319 {
320 $this->debug_dump_function_trace_for_queries = $params['debug_dump_function_trace_for_queries'];
321 }
322
323 if( isset( $debug ) && ! isset( $this->log_queries ) )
324 {
325 // $log_queries follows $debug and respects subclasses, which may define it
329 $this->log_queries = $debug;326 $this->log_queries = $debug;
330 }327 }
331328
332 if( ! extension_loaded('mysql') )329 if( ! extension_loaded( 'mysql' ) )
333 { // The mysql extension is not loaded, try to dynamically load it:330 {
331 // The mysql extension is not loaded, try to dynamically load it
334 $mysql_ext_file = is_windows() ? 'php_mysql.dll' : 'mysql.so';332 $mysql_ext_file = is_windows() ? 'php_mysql.dll' : 'mysql.so';
335 $php_errormsg = null;333 $php_errormsg = null;
336 $old_track_errors = ini_set('track_errors', 1);334 $old_track_errors = ini_set( 'track_errors', 1 );
337 $old_html_errors = ini_set('html_errors', 0);335 $old_html_errors = ini_set( 'html_errors', 0 );
338 @dl( $mysql_ext_file );336 @dl( $mysql_ext_file );
339 $error_msg = $php_errormsg;337 $error_msg = $php_errormsg;
340 if( $old_track_errors !== false ) ini_set('track_errors', $old_track_errors);338 if( $old_track_errors !== false ) ini_set( 'track_errors', $old_track_errors );
341 if( $old_html_errors !== false ) ini_set('html_errors', $old_html_errors);339 if( $old_html_errors !== false ) ini_set( 'html_errors', $old_html_errors );
342340
343 if( ! extension_loaded('mysql') )341 if( ! extension_loaded( 'mysql' ) )
344 { // Still not loaded:342 {
343 // Still not loaded
345 $this->print_error( 'The PHP MySQL module could not be loaded.', '344 $this->print_error( 'The PHP MySQL module could not be loaded.', '
346 <p><strong>Error:</strong> '.$error_msg.'</p>345 <p><strong>Error:</strong> '.$error_msg.'</p>
347 <p>You probably have to edit your php configuration (php.ini) and enable this module ('.$mysql_ext_file.').</p>346 <p>You probably have to edit your php configuration (php.ini) and enable this module ('.$mysql_ext_file.').</p>
@@ -354,16 +353,17 @@
354 $client_flags = isset( $params['client_flags'] ) ? $params['client_flags'] : 0;353 $client_flags = isset( $params['client_flags'] ) ? $params['client_flags'] : 0;
355354
356 if( ! $this->dbhandle )355 if( ! $this->dbhandle )
357 { // Connect to the Database:356 {
357 // Connect to the Database
358 // mysql_error() is tied to an established connection358 // mysql_error() is tied to an established connection
359 // if the connection fails we need a different method to get the error message359 // if the connection fails we need a different method to get the error message
360 $php_errormsg = null;360 $php_errormsg = null;
361 $old_track_errors = ini_set('track_errors', 1);361 $old_track_errors = ini_set( 'track_errors', 1 );
362 $old_html_errors = ini_set('html_errors', 0);362 $old_html_errors = ini_set( 'html_errors', 0 );
363 $this->dbhandle = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );363 $this->dbhandle = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
364 $mysql_error = $php_errormsg;364 $mysql_error = $php_errormsg;
365 if( $old_track_errors !== false ) ini_set('track_errors', $old_track_errors);365 if( $old_track_errors !== false ) ini_set( 'track_errors', $old_track_errors );
366 if( $old_html_errors !== false ) ini_set('html_errors', $old_html_errors);366 if( $old_html_errors !== false ) ini_set( 'html_errors', $old_html_errors );
367 }367 }
368368
369 if( ! $this->dbhandle )369 if( ! $this->dbhandle )
@@ -371,18 +371,19 @@
371 $this->print_error( 'Error establishing a database connection!', '371 $this->print_error( 'Error establishing a database connection!', '
372 <p>('.$mysql_error.')</p>372 <p>('.$mysql_error.')</p>
373 <ol>373 <ol>
374 <li>Are you sure you have typed the correct user/password?</li>374 <li>Are you sure you have typed the correct user/password?</li>
375 <li>Are you sure that you have typed the correct hostname?</li>375 <li>Are you sure that you have typed the correct hostname?</li>
376 <li>Are you sure that the database server is running?</li>376 <li>Are you sure that the database server is running?</li>
377 </ol>', false );377 </ol>', false );
378 }378 }
379 elseif( isset($this->dbname) )379 elseif( isset( $this->dbname ) )
380 {380 {
381 $this->select($this->dbname);381 $this->select( $this->dbname );
382 }382 }
383383
384 if( !empty($params['connection_charset']) )384 if( ! empty( $params['connection_charset'] ) )
385 { // Specify which charset we are using on the client:385 {
386 // Specify which charset we are using on the client
386 $this->set_connection_charset( $params['connection_charset'] );387 $this->set_connection_charset( $params['connection_charset'] );
387 }388 }
388389
@@ -395,8 +396,9 @@
395 */396 */
396397
397398
398 if( isset($params['aliases']) )399 if( isset( $params['aliases'] ) )
399 { // Prepare aliases for replacements:400 {
401 // Prepare aliases for replacements
400 foreach( $params['aliases'] as $dbalias => $dbreplace )402 foreach( $params['aliases'] as $dbalias => $dbreplace )
401 {403 {
402 $this->dbaliases[] = '#\b'.$dbalias.'\b#'; // \b = word boundary404 $this->dbaliases[] = '#\b'.$dbalias.'\b#'; // \b = word boundary
@@ -405,7 +407,8 @@
405 }407 }
406408
407 if( $debug )409 if( $debug )
408 { // Force MySQL strict mode410 {
411 // Force MySQL strict mode
409 // TRADITIONAL mode is only available to mysql > 5.0.2412 // TRADITIONAL mode is only available to mysql > 5.0.2
410 $mysql_version = $this->get_version( 'we do this in DEBUG mode only' );413 $mysql_version = $this->get_version( 'we do this in DEBUG mode only' );
411 if( version_compare( $mysql_version, '5.0.2' ) > 0 )414 if( version_compare( $mysql_version, '5.0.2' ) > 0 )
@@ -419,15 +422,15 @@
419 /**422 /**
420 * Select a DB (if another one needs to be selected)423 * Select a DB (if another one needs to be selected)
421 */424 */
422 function select($db)425 function select( $db )
423 {426 {
424 if( !@mysql_select_db($db, $this->dbhandle) )427 if( !@mysql_select_db( $db, $this->dbhandle ) )
425 {428 {
426 $this->print_error( 'Error selecting database ['.$db.']!', '429 $this->print_error( 'Error selecting database ['.$db.']!', '
427 <ol>430 <ol>
428 <li>Are you sure the database exists?</li>431 <li>Are you sure the database exists?</li>
429 <li>Are you sure the DB user is allowed to use that database?</li>432 <li>Are you sure the DB user is allowed to use that database?</li>
430 <li>Are you sure there is a valid database connection?</li>433 <li>Are you sure there is a valid database connection?</li>
431 </ol>', false );434 </ol>', false );
432 }435 }
433 }436 }
@@ -436,19 +439,19 @@
436 /**439 /**
437 * Format a string correctly for safe insert under all PHP conditions440 * Format a string correctly for safe insert under all PHP conditions
438 */441 */
439 function escape($str)442 function escape( $str )
440 {443 {
441 return mysql_real_escape_string($str, $this->dbhandle);444 return mysql_real_escape_string( $str, $this->dbhandle );
442 }445 }
443446
444447
445 /**448 /**
446 * Quote a value, either in single quotes (and escaped) or if it's NULL as 'NULL'.449 * Quote a value, either in single quotes (and escaped) or if it's NULL as 'NULL'
447 *450 *
448 * @param string|array|null451 * @param string|array|null
449 * @return string Quoted (and escaped) value or 'NULL'.452 * @return string Quoted (and escaped) value or 'NULL'.
450 */453 */
451 function quote($str)454 function quote( $str )
452 {455 {
453 if( is_null( $str ) )456 if( is_null( $str ) )
454 {457 {
@@ -459,26 +462,30 @@
459 $r = '';462 $r = '';
460 foreach( $str as $elt )463 foreach( $str as $elt )
461 {464 {
462 $r .= $this->quote($elt).',';465 $r .= $this->quote( $elt ).',';
463 }466 }
464 return substr( $r, 0, -1 );467 return substr( $r, 0, -1 );
465 }468 }
466 else469 else
467 {470 {
468 return "'".mysql_real_escape_string($str, $this->dbhandle)."'";471 return "'".mysql_real_escape_string( $str, $this->dbhandle )."'";
469 }472 }
470 }473 }
471474
472475
473 /**476 /**
474 * @return string Return the given value or 'NULL', if it's === NULL.477 * @return string Return the given value or 'NULL', if it's === NULL
475 */478 */
476 function null($val)479 function null( $val )
477 {480 {
478 if( $val === NULL )481 if( $val === NULL )
482 {
479 return 'NULL';483 return 'NULL';
484 }
480 else485 else
486 {
481 return $val;487 return $val;
488 }
482 }489 }
483490
484491
@@ -486,7 +493,6 @@
486 * Returns the correct WEEK() function to get the week number for the given date.493 * Returns the correct WEEK() function to get the week number for the given date.
487 *494 *
488 * @link http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html495 * @link http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
489 *
490 * @todo disable when MySQL < 4496 * @todo disable when MySQL < 4
491 * @param string will be used as is497 * @param string will be used as is
492 * @param integer 0 for sunday, 1 for monday498 * @param integer 0 for sunday, 1 for monday
@@ -494,20 +500,18 @@
494 function week( $date, $startofweek )500 function week( $date, $startofweek )
495 {501 {
496 if( $startofweek == 1 )502 if( $startofweek == 1 )
497 { // Week starts on Monday, week 1 must have a monday in this year:503 {
504 // Week starts on Monday, week 1 must have a monday in this year
498 return ' WEEK( '.$date.', 5 ) ';505 return ' WEEK( '.$date.', 5 ) ';
499 }506 }
500507
501 // Week starts on Sunday, week 1 must have a sunday in this year:508 // Week starts on Sunday, week 1 must have a sunday in this year
502 return ' WEEK( '.$date.', 0 ) ';509 return ' WEEK( '.$date.', 0 ) ';
503 }510 }
504511
505512
506 /**513 /**
507 * Print SQL/DB error.514 * Print SQL/DB error
508 *
509 * TODO: fp> bloated: it probably doesn't make sense to display errors if we don't stop. Any use case?
510 * dh> Sure. Local testing (and test cases).
511 *515 *
512 * @param string Short error (no HTML)516 * @param string Short error (no HTML)
513 * @param string Extended description/help for the error (for HTML)517 * @param string Extended description/help for the error (for HTML)
@@ -515,17 +519,19 @@
515 */519 */
516 function print_error( $title = '', $html_str = '', $query_title = '' )520 function print_error( $title = '', $html_str = '', $query_title = '' )
517 {521 {
518 // All errors go to the global error array $EZSQL_ERROR..522 // All errors go to the global error array $EZSQL_ERROR
519 global $EZSQL_ERROR, $is_cli;523 global $EZSQL_ERROR;
524 global $is_cli;
520525
521 $this->error = true;526 $this->error = true;
522527
523 // If no special error string then use mysql default..528 // If no special error string then use mysql default
524 if( ! strlen($title) )529 if( ! strlen( $title ) )
525 {530 {
526 if( is_resource($this->dbhandle) )531 if( is_resource( $this->dbhandle ) )
527 { // use mysql_error:532 {
528 $this->last_error = mysql_error($this->dbhandle).'(Errno='.mysql_errno($this->dbhandle).')';533 // use mysql_error
534 $this->last_error = mysql_error( $this->dbhandle ).'(Errno='.mysql_errno( $this->dbhandle ).')';
529 }535 }
530 else536 else
531 {537 {
@@ -540,23 +546,26 @@
540 // Log this error to the global array..546 // Log this error to the global array..
541 $EZSQL_ERROR[] = array(547 $EZSQL_ERROR[] = array(
542 'query' => $this->last_query,548 'query' => $this->last_query,
543 'error_str' => $this->last_error549 'error_str' => $this->last_error
544 );550 );
545551
546 if( ! ( $this->halt_on_error || $this->show_errors ) )552 if( ! ( $this->halt_on_error || $this->show_errors ) )
547 { // no reason to generate a nice message:553 {
554 // no reason to generate a nice message
548 return;555 return;
549 }556 }
550557
551 if( $this->halt_on_error && ! $this->show_errors )558 if( $this->halt_on_error && ! $this->show_errors )
552 { // do not show errors, just die:559 {
560 // do not show errors, just die
553 die();561 die();
554 }562 }
555563
556 if( $is_cli )564 if( $is_cli )
557 { // Clean error message for command line interface:565 {
566 // Clean error message for command line interface
558 $err_msg = "MySQL error!\n{$this->last_error}\n";567 $err_msg = "MySQL error!\n{$this->last_error}\n";
559 if( ! empty($this->last_query) && $query_title !== false )568 if( ! empty( $this->last_query ) && $query_title !== false )
560 {569 {
561 $err_msg .= "Your query: $query_title\n";570 $err_msg .= "Your query: $query_title\n";
562 $err_msg .= $this->format_query( $this->last_query, false );571 $err_msg .= $this->format_query( $this->last_query, false );
@@ -567,7 +576,7 @@
567 $err_msg = '<p class="error">MySQL error!</p>'."\n";576 $err_msg = '<p class="error">MySQL error!</p>'."\n";
568 $err_msg .= "<div><p><strong>{$this->last_error}</strong></p>\n";577 $err_msg .= "<div><p><strong>{$this->last_error}</strong></p>\n";
569 $err_msg .= $html_str;578 $err_msg .= $html_str;
570 if( !empty($this->last_query) && $query_title !== false )579 if( ! empty( $this->last_query ) && $query_title !== false )
571 {580 {
572 $err_msg .= '<p class="error">Your query: '.$query_title.'</p>';581 $err_msg .= '<p class="error">Your query: '.$query_title.'</p>';
573 $err_msg .= '<pre>';582 $err_msg .= '<pre>';
@@ -579,7 +588,7 @@
579588
580 if( $this->halt_on_error )589 if( $this->halt_on_error )
581 {590 {
582 if( function_exists('debug_die') )591 if( function_exists( 'debug_die' ) )
583 {592 {
584 debug_die( $err_msg );593 debug_die( $err_msg );
585 }594 }
@@ -589,7 +598,8 @@
589 }598 }
590 }599 }
591 elseif( $this->show_errors )600 elseif( $this->show_errors )
592 { // If there is an error then take note of it601 {
602 // If there is an error then take note of it
593 echo '<div class="error">';603 echo '<div class="error">';
594 echo $err_msg;604 echo $err_msg;
595 echo '</div>';605 echo '</div>';
@@ -623,8 +633,9 @@
623 $this->show_errors = false;633 $this->show_errors = false;
624 $this->halt_on_error = false;634 $this->halt_on_error = false;
625635
626 if( ($this->version_long = $this->get_var( 'SELECT VERSION()', 0, 0, $query_title ) ) === NULL )636 if( ( $this->version_long = $this->get_var( 'SELECT VERSION()', 0, 0, $query_title ) ) === NULL )
627 { // Very old version ( < 4.0 )637 {
638 // Very old version ( < 4.0 )
628 $this->version = '';639 $this->version = '';
629 $this->version_long = '';640 $this->version_long = '';
630 }641 }
@@ -646,10 +657,10 @@
646 function save_error_state()657 function save_error_state()
647 {658 {
648 $this->saved_error_states[] = array(659 $this->saved_error_states[] = array(
649 'show_errors' => $this->show_errors,660 'show_errors' => $this->show_errors,
650 'halt_on_error' => $this->halt_on_error,661 'halt_on_error' => $this->halt_on_error,
651 'last_error' => $this->last_error,662 'last_error' => $this->last_error,
652 'error' => $this->error,663 'error' => $this->error,
653 );664 );
654 }665 }
655666
@@ -661,17 +672,16 @@
661 */672 */
662 function restore_error_state()673 function restore_error_state()
663 {674 {
664 if( empty($this->saved_error_states)675 if( empty( $this->saved_error_states ) || ! is_array( $this->saved_error_states ) )
665 || ! is_array($this->saved_error_states) )
666 {676 {
667 return false;677 return false;
668 }678 }
669 $state = array_pop($this->saved_error_states);679 $state = array_pop( $this->saved_error_states );
670680
671 $this->show_errors = $state['show_errors'];681 $this->show_errors = $state['show_errors'];
672 $this->halt_on_error = $state['halt_on_error'];682 $this->halt_on_error = $state['halt_on_error'];
673 $this->last_error = $state['last_error'];683 $this->last_error = $state['last_error'];
674 $this->error = $state['error'];684 $this->error = $state['error'];
675 }685 }
676686
677687
@@ -690,54 +700,63 @@
690 // initialise return700 // initialise return
691 $return_val = 0;701 $return_val = 0;
692702
693 // Flush cached values..703 // Flush cached values
694 $this->flush();704 $this->flush();
695705
696 // Replace aliases:706 // Replace aliases
697 if( ! empty($this->dbaliases) )707 if( ! empty( $this->dbaliases ) )
698 {708 {
699 // TODO: this should only replace the table name part(s), not the whole query!709 // @todo (0000) this should only replace the table name part(s), not the whole
700 // blueyed> I've changed it to replace in table name parts for UPDATE, INSERT and REPLACE, because710 // query! blueyed> I've changed it to replace in table name parts for UPDATE,
701 // it corrupted serialized data..711 // INSERT and REPLACE, because it corrupted serialized data. IMHO, a cleaner
702 // IMHO, a cleaner solution would be to use {T_xxx} in the queries and replace it here. In object properties (e.g. DataObject::$dbtablename), only "T_xxx" would get used and surrounded by "{..}" in the queries it creates.712 // solution would be to use {T_xxx} in the queries and replace it here. In
713 // object properties (e.g. DataObject::$dbtablename), only "T_xxx" would get
714 // used and surrounded by "{..}" in the queries it creates.
703715
704 if( preg_match( '~^\s*(UPDATE\s+)(.*?)(\sSET\s.*)$~is', $query, $match ) )716 if( preg_match( '~^\s*(UPDATE\s+)(.*?)(\sSET\s.*)$~is', $query, $match ) )
705 { // replace only between UPDATE and SET:717 {
718 // replace only between UPDATE and SET
706 $query = $match[1].preg_replace( $this->dbaliases, $this->dbreplaces, $match[2] ).$match[3];719 $query = $match[1].preg_replace( $this->dbaliases, $this->dbreplaces, $match[2] ).$match[3];
707 }720 }
708 elseif( preg_match( '~^\s*(INSERT|REPLACE\s+)(.*?)(\s(VALUES|SET)\s.*)$~is', $query, $match ) )721 elseif( preg_match( '~^\s*(INSERT|REPLACE\s+)(.*?)(\s(VALUES|SET)\s.*)$~is', $query, $match ) )
709 { // replace only between INSERT|REPLACE and VALUES|SET:722 {
723 // replace only between INSERT|REPLACE and VALUES|SET
710 $query = $match[1].preg_replace( $this->dbaliases, $this->dbreplaces, $match[2] ).$match[3];724 $query = $match[1].preg_replace( $this->dbaliases, $this->dbreplaces, $match[2] ).$match[3];
711 }725 }
712 else726 else
713 { // replace in whole query:727 {
728 // replace in whole query
714 $query = preg_replace( $this->dbaliases, $this->dbreplaces, $query );729 $query = preg_replace( $this->dbaliases, $this->dbreplaces, $query );
715730
716 if( ! empty($this->table_options) && preg_match( '#^ \s* create \s* table \s #ix', $query) )731 if( ! empty( $this->table_options ) && preg_match( '#^ \s* create \s* table \s #ix', $query ) )
717 { // Query is a table creation, we add table options:732 {
733 // Query is a table creation, we add table options
718 $query = preg_replace( '~;\s*$~', '', $query ); // remove any ";" at the end734 $query = preg_replace( '~;\s*$~', '', $query ); // remove any ";" at the end
719 $query .= ' '.$this->table_options;735 $query .= ' '.$this->table_options;
720 }736 }
721 }737 }
722 }738 }
723 elseif( ! empty($this->table_options) )739 elseif( ! empty( $this->table_options ) )
724 { // No aliases, but table_options:740 {
741 // No aliases, but table_options
725 if( preg_match( '#^ \s* create \s* table \s #ix', $query) )742 if( preg_match( '#^ \s* create \s* table \s #ix', $query) )
726 { // Query is a table creation, we add table options:743 {
744 // Query is a table creation, we add table options
727 $query = preg_replace( '~;\s*$~', '', $query ); // remove any ";" at the end745 $query = preg_replace( '~;\s*$~', '', $query ); // remove any ";" at the end
728 $query .= $this->table_options;746 $query .= $this->table_options;
729 }747 }
730 }748 }
731749
732 // Keep track of the last query for debug..750 // Keep track of the last query for debug
733 $this->last_query = $query;751 $this->last_query = $query;
734752
735 // Perform the query via std mysql_query function..753 // Perform the query via std mysql_query function
736 $this->num_queries++;754 $this->num_queries++;
737755
738 if( $this->log_queries )756 if( $this->log_queries )
739 { // We want to log queries:757 {
740 $this->queries[ $this->num_queries - 1 ] = array(758 // We want to log queries
759 $this->queries[$this->num_queries-1] = array(
741 'title' => $title,760 'title' => $title,
742 'sql' => $query,761 'sql' => $query,
743 'rows' => -1,762 'rows' => -1,
@@ -745,67 +764,73 @@
745 'results' => 'unknown' );764 'results' => 'unknown' );
746 }765 }
747766
748 if( is_object($Timer) )767 if( is_object( $Timer ) )
749 {768 {
750 // Resume global query timer769 // Resume global query timer
751 $Timer->resume( 'sql_queries' );770 $Timer->resume( 'sql_queries' );
752 // Start a timer for this particular query:771 // Start a timer for this particular query
753 $Timer->start( 'sql_query', false );772 $Timer->start( 'sql_query', false );
754773
755 // Run query:774 // Run query
756 $this->result = @mysql_query( $query, $this->dbhandle );775 $this->result = @mysql_query( $query, $this->dbhandle );
757776
758 if( $this->log_queries )777 if( $this->log_queries )
759 { // We want to log queries:778 {
760 // Get duration for last query:779 // We want to log queries
761 $this->queries[ $this->num_queries - 1 ]['time'] = $Timer->get_duration( 'sql_query', 10 );780 // Get duration for last query
781 $this->queries[$this->num_queries-1]['time'] = $Timer->get_duration( 'sql_query', 10 );
762 }782 }
763783
764 // Pause global query timer:784 // Pause global query timer
765 $Timer->pause( 'sql_queries' );785 $Timer->pause( 'sql_queries' );
766 }786 }
767 else787 else
768 {788 {
769 // Run query:789 // Run query
770 $this->result = @mysql_query( $query, $this->dbhandle );790 $this->result = @mysql_query( $query, $this->dbhandle );
771 }791 }
772792
773 // If there is an error then take note of it..793 // If there is an error then take note of it
774 if( is_resource($this->dbhandle) && mysql_error($this->dbhandle) )794 if( is_resource( $this->dbhandle ) && mysql_error( $this->dbhandle ) )
775 {795 {
776 @mysql_free_result($this->result);796 @mysql_free_result( $this->result );
777 $this->print_error( '', '', $title );797 $this->print_error( '', '', $title );
778 return false;798 return false;
779 }799 }
780800
781 if( preg_match( '#^\s*(INSERT|DELETE|UPDATE|REPLACE)\s#i', $query, $match ) )801 if( preg_match( '#^\s*(INSERT|DELETE|UPDATE|REPLACE)\s#i', $query, $match ) )
782 { // Query was an insert, delete, update, replace:802 {
803 // Query was an insert, delete, update, replace
783804
784 $this->rows_affected = mysql_affected_rows($this->dbhandle);805 $this->rows_affected = mysql_affected_rows( $this->dbhandle );
785 if( $this->log_queries )806 if( $this->log_queries )
786 { // We want to log queries:807 {
787 $this->queries[ $this->num_queries - 1 ]['rows'] = $this->rows_affected;808 // We want to log queries
809 $this->queries[$this->num_queries-1]['rows'] = $this->rows_affected;
788 }810 }
789811
790 // Take note of the insert_id, for INSERT and REPLACE:812 // Take note of the insert_id, for INSERT and REPLACE
791 $match[1] = strtoupper($match[1]);813 $match[1] = strtoupper( $match[1] );
792 if( $match[1] == 'INSERT' || $match[1] == 'REPLACE' )814 if( $match[1] == 'INSERT' || $match[1] == 'REPLACE' )
793 {815 {
794 $this->insert_id = mysql_insert_id($this->dbhandle);816 $this->insert_id = mysql_insert_id( $this->dbhandle );
795 }817 }
796818
797 // Return number of rows affected819 // Return number of rows affected
798 $return_val = $this->rows_affected;820 $return_val = $this->rows_affected;
799 }821 }
800 else822 else
801 { // Query was a select, alter, etc...:823 {
824 // Query was a select, alter, etc...:
802 $this->num_rows = 0;825 $this->num_rows = 0;
803826
804 if( is_resource($this->result) )827 if( is_resource( $this->result ) )
805 { // It's not a resource for CREATE or DROP for example and can even trigger a fatal error (see http://forums.b2evolution.net//viewtopic.php?t=9529)828 {
829 // It's not a resource for CREATE or DROP for example and can even trigger
830 // a fatal error (see http://forums.b2evolution.net//viewtopic.php?t=9529)
806831
807 // Store Query Results832 // Store Query Results
808 while( $row = mysql_fetch_object($this->result) )833 while( $row = mysql_fetch_object( $this->result ) )
809 {834 {
810 // Store relults as an objects within main array835 // Store relults as an objects within main array
811 $this->last_result[$this->num_rows] = $row;836 $this->last_result[$this->num_rows] = $row;
@@ -814,8 +839,9 @@
814 }839 }
815840
816 if( $this->log_queries )841 if( $this->log_queries )
817 { // We want to log queries:842 {
818 $this->queries[ $this->num_queries - 1 ]['rows'] = $this->num_rows;843 // We want to log queries
844 $this->queries[$this->num_queries-1]['rows'] = $this->num_rows;
819 }845 }
820846
821 // Return number of rows selected847 // Return number of rows selected
@@ -823,26 +849,28 @@
823 }849 }
824850
825 if( $this->log_queries )851 if( $this->log_queries )
826 { // We want to log queries:852 {
853 // We want to log queries
827 if( $this->debug_dump_function_trace_for_queries )854 if( $this->debug_dump_function_trace_for_queries )
828 {855 {
829 $this->queries[ $this->num_queries - 1 ]['function_trace'] = debug_get_backtrace( $this->debug_dump_function_trace_for_queries, array( array( 'class' => 'DB' ) ), 1 ); // including first stack entry from class DB856 $this->queries[$this->num_queries-1]['function_trace'] = debug_get_backtrace( $this->debug_dump_function_trace_for_queries, array( array( 'class' => 'DB' ) ), 1 ); // including first stack entry from class DB
830 }857 }
831858
832 if( $this->debug_dump_rows )859 if( $this->debug_dump_rows )
833 {860 {
834 $this->queries[ $this->num_queries - 1 ]['results'] = $this->debug_get_rows_table( $this->debug_dump_rows );861 $this->queries[$this->num_queries-1]['results'] = $this->debug_get_rows_table( $this->debug_dump_rows );
835 }862 }
836 }863 }
837864
838 // Free original query's result:865 // Free original query's result
839 @mysql_free_result($this->result);866 @mysql_free_result( $this->result );
840867
841 // EXPLAIN JOINS ??868 // EXPLAIN JOINS ??
842 if( $this->log_queries && $this->debug_explain_joins && preg_match( '#^ [\s(]* SELECT \s #ix', $query) )869 if( $this->log_queries && $this->debug_explain_joins && preg_match( '#^ [\s(]* SELECT \s #ix', $query) )
843 { // Query was a select, let's try to explain joins...870 {
871 // Query was a select, let's try to explain joins...
844872
845 // save values:873 // save values
846 $saved_last_result = $this->last_result;874 $saved_last_result = $this->last_result;
847 $saved_num_rows = $this->num_rows;875 $saved_num_rows = $this->num_rows;
848876
@@ -853,19 +881,19 @@
853881
854 // Store Query Results882 // Store Query Results
855 $this->num_rows = 0;883 $this->num_rows = 0;
856 while( $row = @mysql_fetch_object($this->result) )884 while( $row = @mysql_fetch_object( $this->result ) )
857 {885 {
858 // Store results as an objects within main array886 // Store results as an objects within main array
859 $this->last_result[$this->num_rows] = $row;887 $this->last_result[$this->num_rows] = $row;
860 $this->num_rows++;888 $this->num_rows++;
861 }889 }
862890
863 $this->queries[ $this->num_queries - 1 ]['explain'] = $this->debug_get_rows_table( 100, true );891 $this->queries[$this->num_queries-1]['explain'] = $this->debug_get_rows_table( 100, true );
864892
865 // Free "EXPLAIN" result resource:893 // Free "EXPLAIN" result resource
866 @mysql_free_result($this->result);894 @mysql_free_result( $this->result );
867895
868 // Restore:896 // Restore
869 $this->last_result = $saved_last_result;897 $this->last_result = $saved_last_result;
870 $this->num_rows = $saved_num_rows;898 $this->num_rows = $saved_num_rows;
871 }899 }
@@ -875,28 +903,28 @@
875903
876904
877 /**905 /**
878 * Get one variable from the DB - see docs for more detail906 * Get one variable from the DB
879 *907 *
880 * Note: To be sure that you received NULL from the DB and not "no rows" check908 * Note: To be sure that you received NULL from the DB and not "no rows" check
881 * for {@link $num_rows}.909 * for {@link $num_rows}.
882 *910 *
883 * @return mixed NULL if not found, the value otherwise (which may also be NULL).911 * @return mixed NULL if not found, the value otherwise (which may also be NULL).
884 */912 */
885 function get_var( $query = NULL, $x = 0, $y = 0, $title = '' )913 function get_var( $query = NULL, $x = 0, $y = 0, $title = '' )
886 {914 {
887 // If there is a query then perform it if not then use cached results..915 // If there is a query then perform it if not then use cached results
888 if( $query )916 if( $query )
889 {917 {
890 $this->query($query, $title);918 $this->query( $query, $title );
891 }919 }
892920
893 // Extract var out of cached results based x,y vals921 // Extract var out of cached results based x,y vals
894 if( $this->last_result[$y] )922 if( $this->last_result[$y] )
895 {923 {
896 $values = array_values(get_object_vars($this->last_result[$y]));924 $values = array_values( get_object_vars( $this->last_result[$y] ) );
897 }925 }
898926
899 if( isset($values[$x]) )927 if( isset( $values[$x] ) )
900 {928 {
901 return $values[$x];929 return $values[$x];
902 }930 }
@@ -906,40 +934,40 @@
906934
907935
908 /**936 /**
909 * Get one row from the DB - see docs for more detail937 * Get one row from the DB
910 *938 *
911 * @return mixed939 * @return mixed
912 */940 */
913 function get_row( $query = NULL, $output = OBJECT, $y = 0, $title = '' )941 function get_row( $query = NULL, $output = OBJECT, $y = 0, $title = '' )
914 {942 {
915 // If there is a query then perform it if not then use cached results..943 // If there is a query then perform it if not then use cached results
916 if( $query )944 if( $query )
917 {945 {
918 $this->query($query, $title);946 $this->query( $query, $title );
919 }947 }
920948
921 // If the output is an object then return object using the row offset..949 // If the output is an object then return object using the row offset
922 if( $output == OBJECT )950 if( $output == OBJECT )
923 {951 {
924 return $this->last_result[$y]952 return $this->last_result[$y]
925 ? $this->last_result[$y]953 ? $this->last_result[$y]
926 : NULL;954 : NULL;
927 }955 }
928 // If the output is an associative array then return row as such..956 // If the output is an associative array then return row as such
929 elseif( $output == ARRAY_A )957 elseif( $output == ARRAY_A )
930 {958 {
931 return $this->last_result[$y]959 return $this->last_result[$y]
932 ? get_object_vars( $this->last_result[$y] )960 ? get_object_vars( $this->last_result[$y] )
933 : array();961 : array();
934 }962 }
935 // If the output is an numerical array then return row as such..963 // If the output is an numerical array then return row as such
936 elseif( $output == ARRAY_N )964 elseif( $output == ARRAY_N )
937 {965 {
938 return $this->last_result[$y]966 return $this->last_result[$y]
939 ? array_values( get_object_vars($this->last_result[$y]) )967 ? array_values( get_object_vars( $this->last_result[$y] ) )
940 : array();968 : array();
941 }969 }
942 // If invalid output type was specified..970 // If invalid output type was specified
943 else971 else
944 {972 {
945 $this->print_error('DB::get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N', '', false);973 $this->print_error('DB::get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N', '', false);
@@ -949,13 +977,12 @@
949977
950 /**978 /**
951 * Function to get 1 column from the cached result set based on X index979 * Function to get 1 column from the cached result set based on X index
952 * see docs for usage and info
953 *980 *
954 * @return array981 * @return array
955 */982 */
956 function get_col( $query = NULL, $x = 0, $title = '' )983 function get_col( $query = NULL, $x = 0, $title = '' )
957 {984 {
958 // If there is a query then perform it if not then use cached results..985 // If there is a query then perform it if not then use cached results
959 if( $query )986 if( $query )
960 {987 {
961 $this->query( $query, $title );988 $this->query( $query, $title );
@@ -963,7 +990,7 @@
963990
964 // Extract the column values991 // Extract the column values
965 $new_array = array();992 $new_array = array();
966 for( $i = 0, $count = count($this->last_result); $i < $count; $i++ )993 for( $i = 0, $count = count( $this->last_result ); $i < $count; $i++ )
967 {994 {
968 $new_array[$i] = $this->get_var( NULL, $x, $i );995 $new_array[$i] = $this->get_var( NULL, $x, $i );
969 }996 }
@@ -979,7 +1006,7 @@
979 */1006 */
980 function get_assoc( $query = NULL, $title = '' )1007 function get_assoc( $query = NULL, $title = '' )
981 {1008 {
982 // If there is a query then perform it if not then use cached results..1009 // If there is a query then perform it if not then use cached results
983 if( $query )1010 if( $query )
984 {1011 {
985 $this->query( $query, $title );1012 $this->query( $query, $title );
@@ -987,7 +1014,7 @@
9871014
988 // Extract the column values1015 // Extract the column values
989 $new_array = array();1016 $new_array = array();
990 for( $i = 0, $count = count($this->last_result); $i < $count; $i++ )1017 for( $i = 0, $count = count( $this->last_result ); $i < $count; $i++ )
991 {1018 {
992 $key = $this->get_var( NULL, 0, $i );1019 $key = $this->get_var( NULL, 0, $i );
9931020
@@ -999,16 +1026,16 @@
9991026
10001027
1001 /**1028 /**
1002 * Return the the query as a result set - see docs for more details1029 * Return the the query as a result set
1003 *1030 *
1004 * @return mixed1031 * @return mixed
1005 */1032 */
1006 function get_results( $query = NULL, $output = OBJECT, $title = '' )1033 function get_results( $query = NULL, $output = OBJECT, $title = '' )
1007 {1034 {
1008 // If there is a query then perform it if not then use cached results..1035 // If there is a query then perform it if not then use cached results
1009 if( $query )1036 if( $query )
1010 {1037 {
1011 $this->query($query, $title);1038 $this->query( $query, $title );
1012 }1039 }
10131040
1014 // Send back array of objects. Each row is an object1041 // Send back array of objects. Each row is an object
@@ -1026,11 +1053,11 @@
10261053
1027 foreach( $this->last_result as $row )1054 foreach( $this->last_result as $row )
1028 {1055 {
1029 $new_array[$i] = get_object_vars($row);1056 $new_array[$i] = get_object_vars( $row );
10301057
1031 if( $output == ARRAY_N )1058 if( $output == ARRAY_N )
1032 {1059 {
1033 $new_array[$i] = array_values($new_array[$i]);1060 $new_array[$i] = array_values( $new_array[$i] );
1034 }1061 }
10351062
1036 $i++;1063 $i++;
@@ -1047,7 +1074,7 @@
10471074
10481075
1049 /**1076 /**
1050 * Get a table (or "<p>No Results.</p>") for the SELECT query results.1077 * Get a table (or "<p>No Results.</p>") for the SELECT query results
1051 *1078 *
1052 * @return string HTML table or "No Results" if the1079 * @return string HTML table or "No Results" if the
1053 */1080 */
@@ -1055,36 +1082,34 @@
1055 {1082 {
1056 $r = '';1083 $r = '';
10571084
1058 if( ! is_resource($this->result) )1085 if( ! is_resource( $this->result ) )
1059 {1086 {
1060 return '<p>No Results.</p>';1087 return '<p>No Results.</p>';
1061 }1088 }
10621089
1063 // Get column info:1090 // Get column info
1064 $col_info = array();1091 $col_info = array();
1065 $n = mysql_num_fields($this->result);1092 $n = mysql_num_fields( $this->result );
1066 $i = 0;1093 $i = 0;
1067 while( $i < $n )1094 while( $i < $n )
1068 {1095 {
1069 $col_info[$i] = mysql_fetch_field($this->result, $i);1096 $col_info[$i] = mysql_fetch_field( $this->result, $i );
1070 $i++;1097 $i++;
1071 }1098 }
10721099
1073 // =====================================================
1074 // Results top rows1100 // Results top rows
1075 $r .= '<table cellspacing="0" summary="Results for query"><tr>';1101 $r .= '<table cellspacing="0" summary="Results for query"><tr>';
1076 for( $i = 0, $count = count($col_info); $i < $count; $i++ )1102 for( $i = 0, $count = count( $col_info ); $i < $count; $i++ )
1077 {1103 {
1078 $r .= '<th><span class="type">'.$col_info[$i]->type.' '.$col_info[$i]->max_length.'</span><br />'1104 $r .= '<th><span class="type">'.$col_info[$i]->type.' '.$col_info[$i]->max_length.'</span><br />'
1079 .$col_info[$i]->name.'</th>';1105 .$col_info[$i]->name.'</th>';
1080 }1106 }
1081 $r .= '</tr>';1107 $r .= '</tr>';
10821108
1083 // ======================================================
1084 // print main results1109 // print main results
1085 if( $this->last_result )1110 if( $this->last_result )
1086 {1111 {
1087 for( $i = 0, $n = min(count($this->last_result), $max_lines); $i < $n; $i++ )1112 for( $i = 0, $n = min( count( $this->last_result ), $max_lines ); $i < $n; $i++ )
1088 {1113 {
1089 $one_row = $this->get_row(NULL, ARRAY_N, $i);1114 $one_row = $this->get_row(NULL, ARRAY_N, $i);
1090 $r .= '<tr>';1115 $r .= '<tr>';
@@ -1111,7 +1136,7 @@
1111 {1136 {
1112 $item = substr( $item, 0, 50 ).'...';1137 $item = substr( $item, 0, 50 ).'...';
1113 }1138 }
1114 $r .= htmlspecialchars($item);1139 $r .= htmlspecialchars( $item );
1115 }1140 }
1116 $r .= '</td>';1141 $r .= '</td>';
1117 }1142 }
@@ -1119,14 +1144,14 @@
1119 $r .= '</tr>';1144 $r .= '</tr>';
1120 }1145 }
11211146
1122 } // if last result1147 }
1123 else1148 else
1124 {1149 {
1125 $r .= '<tr><td colspan="'.(count($col_info)+1).'">No Results</td></tr>';1150 $r .= '<tr><td colspan="'.( count( $col_info )+1 ).'">No Results</td></tr>';
1126 }1151 }
1127 if( $i >= $max_lines )1152 if( $i >= $max_lines )
1128 {1153 {
1129 $r .= '<tr><td colspan="'.(count($col_info)+1).'">Max number of dumped rows has been reached.</td></tr>';1154 $r .= '<tr><td colspan="'.( count( $col_info )+1 ).'">Max number of dumped rows has been reached.</td></tr>';
1130 }1155 }
11311156
1132 $r .= '</table>';1157 $r .= '</table>';
@@ -1137,8 +1162,7 @@
11371162
1138 /**1163 /**
1139 * Format a SQL query1164 * Format a SQL query
1140 * @static1165 *
1141 * @todo dh> Steal the code from phpMyAdmin :)
1142 * @param string SQL1166 * @param string SQL
1143 * @param boolean Format with/for HTML?1167 * @param boolean Format with/for HTML?
1144 */1168 */
@@ -1156,7 +1180,6 @@
1156 }1180 }
11571181
1158 // Split by FROM, WHERE, .. and AND, OR (if there's no comment sign before)1182 // Split by FROM, WHERE, .. and AND, OR (if there's no comment sign before)
1159 // TODO: dh> should not wrap in comments/string literals
1160 $search = array(1183 $search = array(
1161 '~(FROM|WHERE|GROUP BY|ORDER BY|LIMIT|VALUES)~',1184 '~(FROM|WHERE|GROUP BY|ORDER BY|LIMIT|VALUES)~',
1162 '~(AND |OR )~',1185 '~(AND |OR )~',
@@ -1179,6 +1202,7 @@
1179 function dump_queries( $html = true )1202 function dump_queries( $html = true )
1180 {1203 {
1181 global $Timer;1204 global $Timer;
1205
1182 if( is_object( $Timer ) )1206 if( is_object( $Timer ) )
1183 {1207 {
1184 $time_queries = $Timer->get_duration( 'sql_queries' );1208 $time_queries = $Timer->get_duration( 'sql_queries' );
@@ -1191,7 +1215,7 @@
1191 $count_queries = 0;1215 $count_queries = 0;
1192 $count_rows = 0;1216 $count_rows = 0;
11931217
1194 if ( $html )1218 if( $html )
1195 {1219 {
1196 echo '<strong>DB queries:</strong> '.$this->num_queries."<br />\n";1220 echo '<strong>DB queries:</strong> '.$this->num_queries."<br />\n";
1197 }1221 }
@@ -1201,11 +1225,12 @@
1201 }1225 }
12021226
1203 if( ! $this->log_queries )1227 if( ! $this->log_queries )
1204 { // nothing more to do here..1228 {
1229 // nothing more to do here
1205 return;1230 return;
1206 }1231 }
12071232
1208 // Javascript function to toggle DIVs (EXPLAIN, results, backtraces).1233 // Javascript function to toggle DIVs (EXPLAIN, results, backtraces)
1209 if( $html )1234 if( $html )
1210 {1235 {
1211 echo '<script type="text/javascript">1236 echo '<script type="text/javascript">
@@ -1232,11 +1257,13 @@
1232 </script>';1257 </script>';
1233 }1258 }
12341259
1260?><?php
1261
1235 foreach( $this->queries as $i => $query )1262 foreach( $this->queries as $i => $query )
1236 {1263 {
1237 $count_queries++;1264 $count_queries++;
12381265
1239 if ( $html )1266 if( $html )
1240 {1267 {
1241 echo '<h4>Query #'.$count_queries.': '.$query['title']."</h4>\n";1268 echo '<h4>Query #'.$count_queries.': '.$query['title']."</h4>\n";
1242 echo '<code>';1269 echo '<code>';
@@ -1270,7 +1297,7 @@
1270 }1297 }
12711298
1272 // Number of rows with time (percentage and graph, if total time available)1299 // Number of rows with time (percentage and graph, if total time available)
1273 if ( $html )1300 if( $html )
1274 {1301 {
1275 echo '<div class="query_info">';1302 echo '<div class="query_info">';
1276 echo 'Rows: '.$query['rows'];1303 echo 'Rows: '.$query['rows'];
@@ -1289,7 +1316,8 @@
1289 echo number_format( $query['time'], 4 ).'s';1316 echo number_format( $query['time'], 4 ).'s';
12901317
1291 if( $time_queries > 0 )1318 if( $time_queries > 0 )
1292 { // We have a total time we can use to calculate percentage:1319 {
1320 // We have a total time we can use to calculate percentage
1293 echo ' ('.number_format( 100/$time_queries * $query['time'], 2 ).'%)';1321 echo ' ('.number_format( 100/$time_queries * $query['time'], 2 ).'%)';
1294 }1322 }
12951323
@@ -1299,67 +1327,72 @@
1299 }1327 }
13001328
1301 if( $time_queries > 0 )1329 if( $time_queries > 0 )
1302 { // We have a total time we can use to display a graph/bar:1330 {
1331 // We have a total time we can use to display a graph/bar
1303 $perc = round( 100/$time_queries * $query['time'] );1332 $perc = round( 100/$time_queries * $query['time'] );
13041333
1305 if ( $html )1334 if( $html )
1306 {1335 {
1307 echo '<div style="margin:0; padding:0; height:12px; width:'.$perc.'%;'.$style_time_graph.'"></div>';1336 echo '<div style="margin:0; padding:0; height:12px; width:'.$perc.'%;'.$style_time_graph.'"></div>';
1308 }1337 }
1309 else1338 else
1310 { // display an ASCII bar1339 {
1340 // display an ASCII bar
1311 printf( "\n".'[%-50s]', str_repeat( '=', $perc / 2 ) );1341 printf( "\n".'[%-50s]', str_repeat( '=', $perc / 2 ) );
1312 }1342 }
1313 }1343 }
1314 echo $html ? '</div>' : "\n\n";1344 echo $html ? '</div>' : "\n\n";
13151345
1316 // Explain:1346 // Explain
1317 if( isset($query['explain']) )1347 if( isset( $query['explain'] ) )
1318 {1348 {
1319 if( $html )1349 if( $html )
1320 {1350 {
1321 $div_id = 'db_query_explain_'.$i.'_'.md5(serialize($query));1351 $div_id = 'db_query_explain_'.$i.'_'.md5( serialize( $query ) );
1322 echo '<div id="'.$div_id.'">';1352 echo '<div id="'.$div_id.'">';
1323 echo $query['explain'];1353 echo $query['explain'];
1324 echo '</div>';1354 echo '</div>';
1325 echo '<script type="text/javascript">debug_onclick_toggle_div("'.$div_id.'", "Show EXPLAIN", "Hide EXPLAIN");</script>';1355 echo '<script type="text/javascript">debug_onclick_toggle_div("'.$div_id.'", "Show EXPLAIN", "Hide EXPLAIN");</script>';
1326 }1356 }
1327 else1357 else
1328 { // TODO: dh> contains html.1358 {
1359 // @todo (0000) dh> contains html
1329 echo $query['explain'];1360 echo $query['explain'];
1330 }1361 }
1331 }1362 }
13321363
1333 // Results:1364 // Results
1334 if( $query['results'] != 'unknown' )1365 if( $query['results'] != 'unknown' )
1335 {1366 {
1336 if( $html )1367 if( $html )
1337 {1368 {
1338 $div_id = 'db_query_results_'.$i.'_'.md5(serialize($query));1369 $div_id = 'db_query_results_'.$i.'_'.md5( serialize( $query ) );
1339 echo '<div id="'.$div_id.'">';1370 echo '<div id="'.$div_id.'">';
1340 echo $query['results'];1371 echo $query['results'];
1341 echo '</div>';1372 echo '</div>';
1342 echo '<script type="text/javascript">debug_onclick_toggle_div("'.$div_id.'", "Show results", "Hide results");</script>';1373 echo '<script type="text/javascript">debug_onclick_toggle_div("'.$div_id.'", "Show results", "Hide results");</script>';
1343 }1374 }
1344 else1375 else
1345 { // TODO: dh> contains html.1376 {
1377 // @todo (0000) dh> contains html.
1346 echo $query['results'];1378 echo $query['results'];
1347 }1379 }
1348 }1380 }
13491381
1350 // Function trace:1382 // Function trace:
1351 if( isset($query['function_trace']) )1383 if( isset( $query['function_trace'] ) )
1352 {1384 {
1353 if( $html )1385 if( $html )
1354 {1386 {
1355 $div_id = 'db_query_backtrace_'.$i.'_'.md5(serialize($query));1387 $div_id = 'db_query_backtrace_'.$i.'_'.md5( serialize( $query ) );
1356 echo '<div id="'.$div_id.'">';1388 echo '<div id="'.$div_id.'">';
1357 echo $query['function_trace'];1389 echo $query['function_trace'];
1358 echo '</div>';1390 echo '</div>';
1359 echo '<script type="text/javascript">debug_onclick_toggle_div("'.$div_id.'", "Show function trace", "Hide function trace");</script>';1391 echo '<script type="text/javascript">debug_onclick_toggle_div("'.$div_id.'", "Show function trace", "Hide function trace");</script>';
1360 }1392 }
1361 else1393 else
1362 { // TODO: dh> contains html.1394 {
1395 // @todo (0000) dh> contains html.
1363 echo $query['function_trace'];1396 echo $query['function_trace'];
1364 }1397 }
1365 }1398 }
@@ -1376,7 +1409,7 @@
1376 $count_rows += $query['rows'];1409 $count_rows += $query['rows'];
1377 }1410 }
13781411
1379 if ( $html )1412 if( $html )
1380 {1413 {
1381 echo "\n<strong>Total rows:</strong> $count_rows<br />\n";1414 echo "\n<strong>Total rows:</strong> $count_rows<br />\n";
1382 }1415 }
@@ -1390,14 +1423,13 @@
1390 /**1423 /**
1391 * BEGIN A TRANSCATION1424 * BEGIN A TRANSCATION
1392 *1425 *
1393 * Note: By default, MySQL runs with autocommit mode enabled.
1394 * This means that as soon as you execute a statement that updates (modifies)
1395 * a table, MySQL stores the update on disk.
1396 * Once you execute a BEGIN, the updates are "pending" until you execute a
1397 * {@link DB::commit() COMMIT} or a {@link DB:rollback() ROLLBACK}
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches