Overview

Packages

  • Actions
  • Codegen
  • Controls
    • Base
  • DatabaseAdapters
  • Events
  • None
  • Sessions
  • Tests

Classes

  • AbstractControl_CodeGenerator
  • AjaxTimingForm
  • BasicForm
  • BasicOrmTests
  • BBCodeParser
  • CacheTests
  • CalculatorForm
  • CalculatorWidget
  • ComplexColumn
  • DataRepeaterExample
  • Event
  • ExampleCheckColumn1
  • ExampleCheckColumn2
  • ExampleForm
  • Examples
  • ExampleService
  • ExamplesForm
  • ExampleSingleForm
  • ExpandAsArrayTests
  • HtmlJqDoc
  • InjectForm
  • JavaScriptHelper
  • JqAttributes
  • JqControlGen
  • JqDoc
  • JqIcon
  • Method
  • ModelConnectorTests
  • MyControl
  • MyQSlider_ChangeEvent
  • NavPanel
  • NestedTabForm
  • Option
  • Order
  • PaginatorForm
  • ParamsForm
  • PersistentExampleForm
  • PersonEditPanel
  • PluginEditForm
  • PluginManagerForm
  • Project
  • ProjectEditPanel
  • ProjectListForm
  • ProjectPickerListBox
  • ProjectViewPanel
  • QAbstractCacheProvider
  • QAbstractHtmlTableColumn
  • QAbstractHtmlTableDataColumn
  • QAccordion
  • QAccordion_ActivateEvent
  • QAccordion_BeforeActivateEvent
  • QAccordion_CreateEvent
  • QAccordionBase
  • QAccordionGen
  • QAction
  • QActionControl
  • QAjaxAction
  • QAjaxControlAction
  • QAjaxResponse
  • QAlertAction
  • QApplication
  • QApplicationBase
  • QArchive
  • QAutocomplete
  • QAutocomplete_ChangeEvent
  • QAutocomplete_CloseEvent
  • QAutocomplete_CodeGenerator
  • QAutocomplete_CreateEvent
  • QAutocomplete_FocusEvent
  • QAutocomplete_OpenEvent
  • QAutocomplete_ResponseEvent
  • QAutocomplete_SearchEvent
  • QAutocomplete_SelectEvent
  • QAutocomplete_SourceEvent
  • QAutocompleteBase
  • QAutocompleteBase_CodeGenerator
  • QAutocompleteGen
  • QAutocompleteListItem
  • QBackspaceKeyEvent
  • QBaseClass
  • QBlockControl
  • QBlurControlAction
  • QBlurEvent
  • QBorderCollapse
  • QBorderStyle
  • QBrowserType
  • QButton
  • QButtonBase
  • QCache
  • QCacheDeleteAction
  • QCacheDeleteAllAction
  • QCacheProviderAPC
  • QCacheProviderLocalMemory
  • QCacheProviderLocalMemoryTest
  • QCacheProviderMemcache
  • QCacheProviderNoCache
  • QCacheProviderProxy
  • QCacheSetAction
  • QCalendar
  • QCalendarType
  • QCallType
  • QCausesValidation
  • QCellClickEvent
  • QChangeEvent
  • QCheckBox
  • QCheckBox_CodeGenerator
  • QCheckBoxBase_CodeGenerator
  • QCheckBoxLegacyColumn
  • QCheckBoxList
  • QCheckBoxList_CodeGenerator
  • QCheckBoxListBase_CodeGenerator
  • QClickEvent
  • QCodeGen
  • QCodeGenBase
  • QConfirmAction
  • QContextMenuEvent
  • QControl
  • QControl_CodeGenerator
  • QControlBase
  • QControlBase_CodeGenerator
  • QControlBaseTests
  • QControlCategoryType
  • QControlGrouping
  • QControlLabel
  • QControlProxy
  • QConvertNotation
  • QConvertNotationBase
  • QCrossScripting
  • QCryptography
  • QCss
  • QCssAction
  • QCssClassAction
  • QCssTests
  • QCsvTextBox
  • QCursor
  • QDatabaseBase
  • QDatabaseCodeGen
  • QDatabaseFieldBase
  • QDatabaseFieldType
  • QDatabaseForeignKey
  • QDatabaseIndex
  • QDatabaseResultBase
  • QDatabaseRowBase
  • QDatabaseTests
  • QDataGrid
  • QDataGrid_CheckBoxColumn
  • QDataGrid_CodeGenerator
  • QDataGrid_SortEvent
  • QDataGridBase
  • QDataGridBase_CodeGenerator
  • QDataGridLegacy
  • QDataGridLegacyBase
  • QDataGridLegacyColumn
  • QDataGridLegacyRow
  • QDataGridLegacyRowStyle
  • QDataRepeater
  • QDatepicker
  • QDatepicker_BeforeShowDayEvent
  • QDatepicker_BeforeShowEvent
  • QDatepicker_CalculateWeekEvent
  • QDatepicker_ChangeMonthYearEvent
  • QDatepicker_CloseEvent
  • QDatepicker_SelectEvent
  • QDatepicker_SelectEvent2
  • QDatepickerBase
  • QDatepickerBox
  • QDatepickerBox_BeforeShowDayEvent
  • QDatepickerBox_BeforeShowEvent
  • QDatepickerBox_CalculateWeekEvent
  • QDatepickerBox_ChangeMonthYearEvent
  • QDatepickerBox_CloseEvent
  • QDatepickerBox_CodeGenerator
  • QDatepickerBox_SelectEvent
  • QDatepickerBoxBase
  • QDatepickerBoxBase_CodeGenerator
  • QDatepickerBoxGen
  • QDatepickerGen
  • QDateTime
  • QDateTimePicker
  • QDateTimePicker_CodeGenerator
  • QDateTimePickerBase_CodeGenerator
  • QDateTimePickerFormat
  • QDateTimePickerType
  • QDateTimeSpan
  • QDateTimeTests
  • QDateTimeTextBox
  • QDbBackedFormStateHandler
  • QDbBackedSessionHandler
  • QDialog
  • QDialog_BeforeCloseEvent
  • QDialog_ButtonEvent
  • QDialog_CloseEvent
  • QDialog_CreateEvent
  • QDialog_DragEvent
  • QDialog_DragStartEvent
  • QDialog_DragStopEvent
  • QDialog_FocusEvent
  • QDialog_OpenEvent
  • QDialog_ResizeEvent
  • QDialog_ResizeStartEvent
  • QDialog_ResizeStopEvent
  • QDialogBase
  • QDialogBox
  • QDialogGen
  • QDisplayStyle
  • QDoubleClickEvent
  • QDownArrowKeyEvent
  • QDragDropEvent
  • QDraggable
  • QDraggable_CreateEvent
  • QDraggable_DragEvent
  • QDraggable_StartEvent
  • QDraggable_StopEvent
  • QDraggableBase
  • QDraggableGen
  • QDroppable
  • QDroppable_ActivateEvent
  • QDroppable_CreateEvent
  • QDroppable_DeactivateEvent
  • QDroppable_DropEvent
  • QDroppable_OutEvent
  • QDroppable_OverEvent
  • QDroppableBase
  • QDroppableGen
  • QDropZoneGrouping
  • QEmailAttachment
  • QEmailMessage
  • QEmailServer
  • QEmailStringAttachment
  • QEmailTextBox
  • QEnterKeyEvent
  • QErrorAttribute
  • QEscapeKeyEvent
  • QEvent
  • QFieldset
  • QFile
  • QFileAsset
  • QFileAssetBase
  • QFileAssetDialog
  • QFileAssetType
  • QFileControl
  • QFileFormStateHandler
  • QFilterType
  • QFloatTextBox
  • QFloatTextBox_CodeGenerator
  • QFloatTextBoxBase_CodeGenerator
  • QFocusControlAction
  • QFocusEvent
  • QFocusInEvent
  • QFocusOutEvent
  • QFolder
  • QFontFamily
  • QForm
  • QFormBase
  • QFormGen
  • QFormStateHandler
  • QGridLines
  • QHideCalendarAction
  • QHideDialog
  • QHideDialogBox
  • QHListControl
  • QHListItem
  • QHorizontalAlign
  • QHtml
  • QHtmlAttributeManager
  • QHtmlAttributeManagerBase
  • QHtmlReporter
  • QHtmlTable
  • QHtmlTable_CodeGenerator
  • QHtmlTableBase
  • QHtmlTableCallableColumn
  • QHtmlTableCheckBoxColumn
  • QHtmlTableCheckBoxColumn_ClickEvent
  • QHtmlTableIndexedColumn
  • QHtmlTableLinkColumn
  • QHtmlTableNodeColumn
  • QHtmlTablePropertyColumn
  • QI18n
  • QI18nTests
  • QImageBase
  • QImageBrowser
  • QImageBrowserBase
  • QImageBrowserNav
  • QImageBrowserThumbnails
  • QImageButton
  • QImageControl
  • QImageControlBase
  • QImageFileAsset
  • QImageLabel
  • QImageLabelBase
  • QImageRollover
  • QImageType
  • QIndex
  • QInformixPdoDatabase
  • QInformixPdoDatabaseField
  • QInformixPdoDatabaseResult
  • QInformixPdoDatabaseRow
  • QInputEvent
  • QInstallationValidationResult
  • QInstallationValidator
  • QIntegerTextBox
  • QIntegerTextBox_CodeGenerator
  • QIntegerTextBoxBase_CodeGenerator
  • QJavaScriptAction
  • QJQAction
  • QJQBounceAction
  • QJqButton
  • QJqButton_CreateEvent
  • QJqButtonBase
  • QJqButtonGen
  • QJqCheckBox
  • QJqCheckBox_CreateEvent
  • QJqCheckBoxBase
  • QJqCheckBoxGen
  • QJQHideAction
  • QJQHideEffectAction
  • QJQHighlightAction
  • QJQPulsateAction
  • QJqRadioButton
  • QJqRadioButton_CreateEvent
  • QJqRadioButtonBase
  • QJqRadioButtonGen
  • QJQShakeAction
  • QJQShowAction
  • QJQShowEffectAction
  • QJQSizeAction
  • QJQToggleAction
  • QJQToggleEffectAction
  • QJQTransferAction
  • QJqUiEvent
  • QJqUiPropertyEvent
  • QJsClosure
  • QJsFunction
  • QJsNoQuoteKey
  • QJsParameterList
  • QJsPriority
  • QJsTimer
  • QJsTimerBase
  • QJsVarName
  • QKeyDownEvent
  • QKeyPressEvent
  • QKeyUpEvent
  • QLabel
  • QLabel_CodeGenerator
  • QLabelBase_CodeGenerator
  • QLexer
  • QLinkButton
  • QListBox
  • QListBox_CodeGenerator
  • QListBoxBase
  • QListBoxBase_CodeGenerator
  • QListControl
  • QListControl_CodeGenerator
  • QListControlBase_CodeGenerator
  • QListItem
  • QListItemBase
  • QListItemStyle
  • QManyToManyReference
  • QMenu
  • QMenu_BlurEvent
  • QMenu_CreateEvent
  • QMenu_FocusEvent
  • QMenu_SelectEvent
  • QMenuBase
  • QMenuGen
  • QMimeType
  • QModelConnectorArgumentType
  • QModelConnectorCreateType
  • QModelConnectorEditDlg
  • QModelConnectorOptions
  • QModelConnectorParam
  • QMouseDownEvent
  • QMouseEnterEvent
  • QMouseLeaveEvent
  • QMouseMoveEvent
  • QMouseOutEvent
  • QMouseOverEvent
  • QMouseUpEvent
  • QMultiLevelCacheProvider
  • QMySqlDatabase
  • QMySqlDatabaseField
  • QMySqlDatabaseResult
  • QMySqli5ClusterDatabase
  • QMySqli5Database
  • QMySqli5DatabaseField
  • QMySqli5DatabaseResult
  • QMySqliDatabase
  • QMySqliDatabaseField
  • QMySqliDatabaseResult
  • QMySqliDatabaseRow
  • QNoScriptAjaxAction
  • QNumericTextBox
  • QOnEvent
  • QOracleDatabase
  • QOracleDatabaseField
  • QOracleDatabaseResult
  • QOracleDatabaseRow
  • QOrderedListType
  • QOverflow
  • QPaginatedControl
  • QPaginator
  • QPaginatorBase
  • QPanel
  • QPartialQueryBuilder
  • QPdoDatabase
  • QPdoDatabaseResult
  • QPgConditionILike
  • QPgConditionJsonContains
  • QPgQ
  • QPosition
  • QPostgreSqlDatabase
  • QPostgreSqlDatabaseField
  • QPostgreSqlDatabaseResult
  • QPostgreSqlDatabaseRow
  • QPostgreSqlPdoDatabase
  • QPostgreSqlPdoDatabaseField
  • QPostgreSqlPdoDatabaseResult
  • QPostgreSqlPdoDatabaseRow
  • QProgressbar
  • QProgressbar_ChangeEvent
  • QProgressbar_CompleteEvent
  • QProgressbar_CreateEvent
  • QProgressbarBase
  • QProgressbarGen
  • QQ
  • QQAggregationClause
  • QQAliasTests
  • QQAssociationNode
  • QQAverage
  • QQClause
  • QQColumnNode
  • QQCondition
  • QQConditionAll
  • QQConditionAnd
  • QQConditionBetween
  • QQConditionComparison
  • QQConditionEqual
  • QQConditionExists
  • QQConditionGreaterOrEqual
  • QQConditionGreaterThan
  • QQConditionIn
  • QQConditionIsNotNull
  • QQConditionIsNull
  • QQConditionLessOrEqual
  • QQConditionLessThan
  • QQConditionLike
  • QQConditionLogical
  • QQConditionNone
  • QQConditionNot
  • QQConditionNotBetween
  • QQConditionNotEqual
  • QQConditionNotExists
  • QQConditionNotIn
  • QQConditionNotLike
  • QQConditionOr
  • QQCount
  • QQDistinct
  • QQExpand
  • QQExpandAsArray
  • QQExpandVirtualNode
  • QQFuncTests
  • QQFunctionNode
  • QQGroupBy
  • QQHavingClause
  • QQLimitInfo
  • QQMathNode
  • QQMathOpTests
  • QQMaximum
  • QQMinimum
  • QQNamedValue
  • QQNode
  • QQNoParentNode
  • QQOrderBy
  • QQReverseReferenceNode
  • QQSelect
  • QQSubQueryCountNode
  • QQSubQueryNode
  • QQSubQuerySqlNode
  • QQSum
  • QQTableNode
  • QQuery
  • QQueryBuilder
  • QQueryExpansion
  • QQVirtualNode
  • QRadioButton
  • QRadioButtonList
  • QRadioButtonList_CodeGenerator
  • QRadioButtonListBase_CodeGenerator
  • QRedirectAction
  • QReference
  • QRegex
  • QRegisterClickPositionAction
  • QRepeatDirection
  • QRequestMode
  • QResetTimerAction
  • QResizable
  • QResizable_CreateEvent
  • QResizable_ResizeEvent
  • QResizable_StartEvent
  • QResizable_StopEvent
  • QResizableBase
  • QResizableGen
  • QResizeHandleDirection
  • QRestServiceCodeGen
  • QReverseReference
  • QRssCategory
  • QRssFeed
  • QRssImage
  • QRssItem
  • QSampleControl
  • QSampleTranslation
  • QSelectable
  • QSelectable_CreateEvent
  • QSelectable_SelectedEvent
  • QSelectable_SelectingEvent
  • QSelectable_StartEvent
  • QSelectable_StopEvent
  • QSelectable_UnselectedEvent
  • QSelectable_UnselectingEvent
  • QSelectableBase
  • QSelectableGen
  • QSelectControlAction
  • QSelectEvent
  • QSelectionMode
  • QSelectMenu
  • QSelectMenu_ChangeEvent
  • QSelectMenu_CloseEvent
  • QSelectMenu_CreateEvent
  • QSelectMenu_FocusEvent
  • QSelectMenu_OpenEvent
  • QSelectMenu_SelectEvent
  • QSelectMenuBase
  • QSelectMenuGen
  • QServerAction
  • QServerControlAction
  • QSessionFormStateHandler
  • QSetValueAction
  • QShowCalendarAction
  • QShowDialog
  • QShowDialogBox
  • QSlider
  • QSlider_ChangeEvent
  • QSlider_CodeGenerator
  • QSlider_CreateEvent
  • QSlider_SlideEvent
  • QSlider_StartEvent
  • QSlider_StopEvent
  • QSliderBase
  • QSliderBase_CodeGenerator
  • QSliderGen
  • QSoapMethod
  • QSoapParameter
  • QSoapService
  • QSortable
  • QSortable_ActivateEvent
  • QSortable_BeforeStopEvent
  • QSortable_ChangeEvent
  • QSortable_CreateEvent
  • QSortable_DeactivateEvent
  • QSortable_OutEvent
  • QSortable_OverEvent
  • QSortable_ReceiveEvent
  • QSortable_RemoveEvent
  • QSortable_SortEvent
  • QSortable_StartEvent
  • QSortable_StopEvent
  • QSortable_UpdateEvent
  • QSortableBase
  • QSortableGen
  • QSpinner
  • QSpinner_ChangeEvent
  • QSpinner_CreateEvent
  • QSpinner_SpinEvent
  • QSpinner_StartEvent
  • QSpinner_StopEvent
  • QSpinnerBase
  • QSpinnerGen
  • QSqlColumn
  • QSqLite3PdoDatabase
  • QSqLite3PdoDatabaseField
  • QSqLite3PdoDatabaseResult
  • QSqLite3PdoDatabaseRow
  • QSqlServer2005Database
  • QSqlServer2005DatabaseField
  • QSqlServer2005DatabaseResult
  • QSqlServer2005DatabaseRow
  • QSqlServerDatabase
  • QSqlServerDatabaseField
  • QSqlServerDatabaseResult
  • QSqlServerDatabaseRow
  • QSqlTable
  • QStack
  • QStopPropagationAction
  • QString
  • QStringTest
  • QTabKeyEvent
  • QTabs
  • QTabs_ActivateEvent
  • QTabs_BeforeActivateEvent
  • QTabs_BeforeLoadEvent
  • QTabs_CreateEvent
  • QTabs_LoadEvent
  • QTabsBase
  • QTabsGen
  • QTag
  • QTagStyler
  • QTerminateAction
  • QTestControl
  • QTestForm
  • QTextAlign
  • QTextBox
  • QTextBox_CodeGenerator
  • QTextBoxBase
  • QTextBoxBase_CodeGenerator
  • QTextMode
  • QTimer
  • QTimerExpiredEvent
  • QTimerTests
  • QToggleCssClassAction
  • QToggleDisplayAction
  • QToggleEnableAction
  • QTranslationPoParser
  • QTreeNav
  • QTreeNavItem
  • QType
  • QTypeTable
  • QTypeTests
  • QUnitTestCaseBase
  • QUnorderedListStyle
  • QUpArrowKeyEvent
  • QUrlTextBox
  • QVerticalAlign
  • QVirtualAttributeColumn
  • QWaitIcon
  • QWatcher
  • QWatcherBase
  • QWatcherCache
  • QWatcherDB
  • QWatcherNone
  • QWriteBox
  • RecordsSummary
  • RefreshForm
  • SampleComposite
  • SampleForm
  • SelectableLabel
  • SelectForm
  • SpeedForm
  • TestImageBrowser
  • UrlForm

Interfaces

  • ICacheAction
  • QDataList_CodeGenerator_Interface
  • QTranslationBase

Traits

  • QDataBinder
  • QListItemManager
  • QModelTrait

Exceptions

  • QCallerException
  • QCrossScriptingException
  • QCryptographyException
  • QDatabaseExceptionBase
  • QDataBindException
  • QDateTimeNullException
  • QEmailException
  • QIndexOutOfRangeException
  • QInformixPdoDatabaseException
  • QInvalidCastException
  • QInvalidFormStateException
  • QMySqliDatabaseException
  • QOptimisticLockingException
  • QOracleDatabaseException
  • QPdoDatabaseException
  • QPoParserException
  • QPostgreSqlDatabaseException
  • QPostgreSqlPdoDatabaseException
  • QRemoteAdminDeniedException
  • QSqLite3PdoDatabaseException
  • QSqlServer2005DatabaseException
  • QSqlServerDatabaseException
  • QUndefinedMethodException
  • QUndefinedPrimaryKeyException
  • QUndefinedPropertyException

Functions

  • __database_check_error
  • __QForm_EvaluateTemplate_ObHandler
  • _b
  • _indent
  • _nl
  • _p
  • _r
  • _t
  • _tp
  • _tr
  • array_trim
  • beginsWith
  • CamelCaseFromDash
  • CastToInt
  • DataGridEvalHandleError
  • DisplayMonospacedText
  • endsWith
  • GO_BACK
  • jq_anytime_gen
  • jq_control_gen
  • jq_inc_gen
  • jq_indent
  • PrintExplainStatement
  • PrintInstructions
  • QcubedHandleCodeGenParseError
  • QcubedHandleError
  • QcubedHandleException
  • QCubedShutdown
  • QDateTimeErrorHandler
  • trimOffEnd
  • trimOffFront
  • Overview
  • Package
  • Class
   1: <?php
   2:     if(!class_exists('QAbstractCacheProvider')){
   3:         include_once __QCUBED_CORE__ . '/framework/QAbstractCacheProvider.class.php';
   4:     }
   5:     
   6:     /**
   7:      * The interface for cache actions to be queued and replayed.
   8:      */
   9:     interface ICacheAction {
  10:         /**
  11:          * Executes action on the given cache object
  12:          * @param QAbstractCacheProvider $objCache The cache object to apply this action to.
  13:          */
  14:         public function Execute(QAbstractCacheProvider $objCache);
  15:     }
  16:     /**
  17:      * The Set cache action to be queued and replayed.
  18:      */
  19:     class QCacheSetAction implements ICacheAction {
  20:         /**
  21:          * @var string the key to use for the object
  22:          */
  23:         protected $strKey;
  24:         /**
  25:          * @var object the object to put in the cache
  26:          */
  27:         protected $objValue;
  28: 
  29:         /**
  30:          * Construct the new QCacheSetAction object.
  31:          *
  32:          * @param string $strKey   the key to use for the object
  33:          * @param object $objValue the object to put in the cache
  34:          */
  35:         public function __construct($strKey, $objValue) {
  36:             $this->strKey = $strKey;
  37:             $this->objValue = $objValue;
  38:         }
  39: 
  40:         /**
  41:          * Executes action on the given cache object
  42:          * @param QAbstractCacheProvider $objCache The cache object to apply this action to.
  43:          */
  44:         public function Execute(QAbstractCacheProvider $objCache) {
  45:             $objCache->Set($this->strKey, $this->objValue);
  46:         }
  47:     }
  48:     /**
  49:      * The Delete cache action to be queued and replayed.
  50:      */
  51:     class QCacheDeleteAction implements ICacheAction {
  52:         /**
  53:          * @var string the key to use for the object
  54:          */
  55:         protected $strKey;
  56: 
  57:         /**
  58:          * Construct the new QCacheDeleteAction object.
  59:          * @param string $strKey the key to use for the object
  60:          */
  61:         public function __construct($strKey) {
  62:             $this->strKey = $strKey;
  63:         }
  64: 
  65:         /**
  66:          * Executes action on the given cache object
  67:          * @param QAbstractCacheProvider $objCache The cache object to apply this action to.
  68:          */
  69:         public function Execute(QAbstractCacheProvider $objCache) {
  70:             $objCache->Delete($this->strKey);
  71:         }
  72:     }
  73:     /**
  74:      * The DeleteAll cache action to be queued and replayed.
  75:      */
  76:     class QCacheDeleteAllAction implements ICacheAction {
  77:         /**
  78:          * Construct the new QCacheDeleteAction object.
  79:          */
  80:         public function __construct() {
  81:         }
  82: 
  83:         /**
  84:          * Executes action on the given cache object
  85:          * @param QAbstractCacheProvider $objCache The cache object to apply this action to.
  86:          */
  87:         public function Execute(QAbstractCacheProvider $objCache) {
  88:             $objCache->DeleteAll();
  89:         }
  90:     }
  91:     /**
  92:      * Cache provider that records all additions and removals from the cache,
  93:      * and provides an interface to replay them on another instance of an QAbstractCacheProvider
  94:      */
  95:     class QCacheProviderProxy extends QAbstractCacheProvider {
  96:         /**
  97:          * @var array Additions to cache
  98:          */
  99:         protected $arrLocalCacheAdditions;
 100: 
 101:         /**
 102:          * @var array Removals from cache
 103:          */
 104:         protected $arrLocalCacheRemovals;
 105: 
 106:         /**
 107:          * @var QAbstractCacheProvider The super cache to query values from.
 108:          */
 109:         protected $objSuperCache;
 110: 
 111:         /**
 112:          * @var ICacheAction[] The queue of actions performed on this cache. 
 113:          */
 114:         protected $objCacheActionQueue;
 115: 
 116:         /**
 117:          * @param QAbstractCacheProvider $objSuperCache The super cache to query values from.
 118:          */
 119:         public function __construct($objSuperCache) {
 120:             $this->objSuperCache = $objSuperCache;
 121:             $this->objCacheActionQueue = array();
 122:             $this->arrLocalCacheAdditions = array();
 123:             $this->arrLocalCacheRemovals = array();
 124:         }
 125:         
 126:         /**
 127:          * Apply changes to the cache object supplyed.
 128:          *
 129:          * @param QAbstractCacheProvider $objAbstractCacheProvider The cache object to apply changes.
 130:          */
 131:         public function Replay($objAbstractCacheProvider) {
 132:             foreach ($this->objCacheActionQueue as $objCacheAction) {
 133:                 $objCacheAction->Execute($objAbstractCacheProvider);
 134:             }
 135:             $this->objCacheActionQueue = array();
 136:         }
 137:             
 138:         public function Get($strKey) {
 139:             if (isset($this->arrLocalCacheAdditions[$strKey])) {
 140:                 return $this->arrLocalCacheAdditions[$strKey];
 141:             }
 142:             if (!isset($this->arrLocalCacheRemovals[$strKey])) {
 143:                 if ($this->objSuperCache) {
 144:                     return $this->objSuperCache->Get($strKey);
 145:                 }
 146:             }
 147:             return false;
 148:         }
 149: 
 150:         public function Set($strKey, $objValue) {
 151:             $this->arrLocalCacheAdditions[$strKey] = $objValue;
 152:             if (isset($this->arrLocalCacheRemovals[$strKey])) {
 153:                 unset($this->arrLocalCacheRemovals[$strKey]);
 154:             }
 155:             $this->objCacheActionQueue[] = new QCacheSetAction($strKey, $objValue);
 156:         }
 157: 
 158:         public function Delete($strKey) {
 159:             if (isset($this->arrLocalCacheAdditions[$strKey])) {
 160:                 unset($this->arrLocalCacheAdditions[$strKey]);
 161:             }
 162:             $this->arrLocalCacheRemovals[$strKey] = true;
 163:             $this->objCacheActionQueue[] = new QCacheDeleteAction($strKey);
 164:         }
 165: 
 166:         public function DeleteAll() {
 167:             $this->arrLocalCacheAdditions = array();
 168:             $this->arrLocalCacheRemovals = array();
 169:             $this->objCacheActionQueue[] = new QCacheDeleteAllAction;
 170:         }
 171:     }
 172: 
 173:     /**
 174:      * Every database adapter must implement the following 5 classes (all of which are abstract):
 175:      * * DatabaseBase
 176:      * * DatabaseFieldBase
 177:      * * DatabaseResultBase
 178:      * * DatabaseRowBase
 179:      * * DatabaseExceptionBase
 180:      * This Database library also has the following classes already defined, and
 181:      * Database adapters are assumed to use them internally:
 182:      * * DatabaseIndex
 183:      * * DatabaseForeignKey
 184:      * * DatabaseFieldType (which is an abstract class that solely contains constants)
 185:      *
 186:      * @property-read string  $EscapeIdentifierBegin
 187:      * @property-read string  $EscapeIdentifierEnd
 188:      * @property-read boolean $EnableProfiling
 189:      * @property-read int     $AffectedRows
 190:      * @property-read string  $Profile
 191:      * @property-read int     $DatabaseIndex
 192:      * @property-read int     $Adapter
 193:      * @property-read string  $Server
 194:      * @property-read string  $Port
 195:      * @property-read string  $Database
 196:      * @property-read string  $Service
 197:      * @property-read string  $Protocol
 198:      * @property-read string  $Host
 199:      * @property-read string  $Username
 200:      * @property-read string  $Password
 201:      * @property boolean      $Caching         if true objects loaded from this database will be kept in cache (assuming a cache provider is also configured)
 202:      * @property-read string  $DateFormat
 203:      * @property-read boolean $OnlyFullGroupBy database adapter sub-classes can override and set this property to true
 204:      *          to prevent the behavior of automatically adding all the columns to the select clause when the query has
 205:      *          an aggregation clause.
 206:      * @package DatabaseAdapters
 207:      */
 208:     abstract class QDatabaseBase extends QBaseClass {
 209:         // Must be updated for all Adapters
 210:         /** Adapter name */
 211:         const Adapter = 'Generic Database Adapter (Abstract)';
 212: 
 213:         // Protected Member Variables for ALL Database Adapters
 214:         /** @var int Database Index according to the configuration file */
 215:         protected $intDatabaseIndex;
 216:         /** @var bool Has the profiling been enabled? */
 217:         protected $blnEnableProfiling;
 218:         protected $strProfileArray;
 219: 
 220:         protected $objConfigArray;
 221:         protected $blnConnectedFlag = false;
 222: 
 223:         /** @var string The beginning part of characters which can escape identifiers in a SQL query for the database */
 224:         protected $strEscapeIdentifierBegin = '"';
 225:         /** @var string The ending part of characters which can escape identifiers in a SQL query for the database */
 226:         protected $strEscapeIdentifierEnd = '"';
 227:         protected $blnOnlyFullGroupBy = false; // should be set in sub-classes as appropriate
 228:         
 229:         /**
 230:          * @var int The transaction depth value.
 231:          * It is incremented on a transaction begin,
 232:          * decremented on a transaction commit, and reset to zero on a roll back.
 233:          * It is used to implement the recursive transaction functionality.
 234:          */
 235:         protected $intTransactionDepth = 0;
 236:         
 237:         /**
 238:          * @var QStack The stack of cache providers.
 239:          * It is populated with cache providers from different databases,
 240:          * if there are transaction of one DB in the middle of the transaction of another DB.
 241:          */
 242:         protected static $objCacheProviderStack;
 243: 
 244:         // Abstract Methods that ALL Database Adapters MUST implement
 245:         /**
 246:          * Connects to the database
 247:          */
 248:         abstract public function Connect();
 249:         // these are protected - externally, the "Query/NonQuery" wrappers are meant to be called
 250:         /**
 251:          * Sends a SQL query for execution to the database
 252:          * In this regard, a query is a 'SELECT' statement
 253:          *
 254:          * @param string $strQuery The Query to be executed
 255:          *
 256:          * @return mixed Result that the database returns after running the query.
 257:          */
 258:         abstract protected function ExecuteQuery($strQuery);
 259: 
 260:         /**
 261:          * Sends a non-SELECT query (such as INSERT, UPDATE, DELETE, TRUNCATE) to DB server.
 262:          * In most cases, the results of this function are not used and you should not send
 263:          * 'SELECT' queries using this method because a result is not guaranteed to be returned
 264:          *
 265:          * If there was an error, it would most probably be caught as an exception.
 266:          *
 267:          * @param string $strNonQuery The Query to be executed
 268:          *
 269:          * @return mixed Result that the database returns after running the query
 270:          */
 271:         abstract protected function ExecuteNonQuery($strNonQuery);
 272: 
 273:         /**
 274:          * Returns the list of tables in the database (as string)
 275:          *
 276:          * @return mixed|string[] List of tables
 277:          */
 278:         abstract public function GetTables();
 279: 
 280:         /**
 281:          * Returns the ID to be inserted in a table column (normally it an autoincrement column)
 282:          *
 283:          * @param null|string $strTableName  Table name where the ID has to be inserted
 284:          * @param null|string $strColumnName Column name where the ID has to be inserted
 285:          *
 286:          * @return mixed
 287:          */
 288:         abstract public function InsertId($strTableName = null, $strColumnName = null);
 289: 
 290:         /**
 291:          * Get the list of columns/fields for a given table
 292:          *
 293:          * @param string $strTableName Name of table whose fields we have to get
 294:          *
 295:          * @return mixed
 296:          */
 297:         abstract public function GetFieldsForTable($strTableName);
 298: 
 299:         /**
 300:          * Get list of indexes for a table
 301:          *
 302:          * @param string $strTableName Name of table whose column indexes we have to get
 303:          *
 304:          * @return mixed
 305:          */
 306:         abstract public function GetIndexesForTable($strTableName);
 307: 
 308:         /**
 309:          * Get list of foreign keys for a table
 310:          *
 311:          * @param string $strTableName Name of table whose foreign keys we are trying to get
 312:          *
 313:          * @return mixed
 314:          */
 315:         abstract public function GetForeignKeysForTable($strTableName);
 316: 
 317:         /**
 318:          * This function actually begins the database transaction.
 319:          * Must be implemented in all subclasses.
 320:          * The "TransactionBegin" wrapper are meant to be called by end-user code
 321:          *
 322:          * @return void Nothing
 323:          */
 324:         abstract protected function ExecuteTransactionBegin();
 325: 
 326:         /**
 327:          * This function actually commits the database transaction.
 328:          * Must be implemented in all subclasses.
 329:          * The "TransactionCommit" wrapper are meant to be called by end-user code
 330:          * @return void Nothing
 331:          */
 332:         abstract protected function ExecuteTransactionCommit();
 333: 
 334:         /**
 335:          * This function actually rolls back the database transaction.
 336:          * Must be implemented in all subclasses.
 337:          * The "TransactionRollBack" wrapper are meant to be called by end-user code
 338:          *
 339:          * @return void Nothing
 340:          */
 341:         abstract protected function ExecuteTransactionRollBack();
 342: 
 343:         /**
 344:          * Template for executing stored procedures. Optional, for those database drivers that support it.
 345:          * @param $strProcName
 346:          * @param null $params
 347:          * @return mixed
 348:          */
 349:         public function ExecuteProcedure($strProcName, $params = null) {}
 350: 
 351:         /**
 352:          * This function begins the database transaction.
 353:          *
 354:          * @return void Nothing
 355:          */
 356:         public final function TransactionBegin() {
 357:             if (0 == $this->intTransactionDepth) {
 358:                 $this->ExecuteTransactionBegin();
 359:                 $objCacheProvider = QApplication::$objCacheProvider;
 360:                 if ($objCacheProvider && $this->Caching && !($objCacheProvider instanceof QCacheProviderNoCache)) {
 361:                     if (!self::$objCacheProviderStack) {
 362:                         self::$objCacheProviderStack = new QStack;
 363:                     }
 364:                     self::$objCacheProviderStack->Push($objCacheProvider);
 365:                     QApplication::$objCacheProvider = new QCacheProviderProxy($objCacheProvider);
 366:                 }
 367:             }
 368:             $this->intTransactionDepth++;
 369:         }
 370: 
 371:         /**
 372:          * This function commits the database transaction.
 373:          *
 374:          * @throws QCallerException
 375:          * @return void Nothing
 376:          */
 377:         public final function TransactionCommit() {
 378:             if (1 == $this->intTransactionDepth) {
 379:                 $this->ExecuteTransactionCommit();
 380:                 $this->transactionCacheFlush();
 381:                 $this->transactionCacheRestore();
 382:             }
 383:             if ($this->intTransactionDepth <= 0) {
 384:                 throw new QCallerException("The transaction commit call is called before the transaction begin was called.");
 385:             }
 386:             $this->intTransactionDepth--;
 387:         }
 388: 
 389:         /**
 390:          * This function rolls back the database transaction.
 391:          *
 392:          * @return void Nothing
 393:          */
 394:         public final function TransactionRollBack() {
 395:             $this->ExecuteTransactionRollBack();
 396:             $this->intTransactionDepth = 0;
 397:             $this->transactionCacheRestore();
 398:         }
 399:         
 400:         /**
 401:          * Flushes all objects from the local cache to the actual one.
 402:          */
 403:         protected final function transactionCacheFlush() {
 404:             if (!self::$objCacheProviderStack || self::$objCacheProviderStack->IsEmpty()) {
 405:                 return;
 406:             }
 407:             $objCacheProvider = self::$objCacheProviderStack->PeekLast();
 408:             QApplication::$objCacheProvider->Replay($objCacheProvider);
 409:         }
 410: 
 411:         /**
 412:          * Restores the actual cache to the QApplication variable.
 413:          */
 414:         protected final function transactionCacheRestore() {
 415:             if (!self::$objCacheProviderStack || self::$objCacheProviderStack->IsEmpty()) {
 416:                 return;
 417:             }
 418:             $objCacheProvider = self::$objCacheProviderStack->Pop();
 419:             // restore the actual cache to the QApplication variable.
 420:             QApplication::$objCacheProvider = $objCacheProvider;
 421:         }
 422: 
 423:         abstract public function SqlLimitVariablePrefix($strLimitInfo);
 424:         abstract public function SqlLimitVariableSuffix($strLimitInfo);
 425:         abstract public function SqlSortByVariable($strSortByInfo);
 426: 
 427:         /**
 428:          * Closes the database connection
 429:          *
 430:          * @return mixed
 431:          */
 432:         abstract public function Close();
 433: 
 434:         /**
 435:          * Given an identifier for a SQL query, this method returns the escaped identifier
 436:          *
 437:          * @param string $strIdentifier Identifier to be escaped
 438:          *
 439:          * @return string Escaped identifier string
 440:          */
 441:         public function EscapeIdentifier($strIdentifier) {
 442:             return $this->strEscapeIdentifierBegin . $strIdentifier . $this->strEscapeIdentifierEnd;
 443:         }
 444: 
 445:         /**
 446:          * Given an array of identifiers, this method returns array of escaped identifiers
 447:          * For corner case handling, if a single identifier is supplied, a single escaped identifier is returned
 448:          *
 449:          * @param array|string $mixIdentifiers Array of escaped identifiers (array) or one unescaped identifier (string)
 450:          *
 451:          * @return array|string Array of escaped identifiers (array) or one escaped identifier (string)
 452:          */
 453:         public function EscapeIdentifiers($mixIdentifiers) {
 454:             if (is_array($mixIdentifiers)) {
 455:                 return array_map(array($this, 'EscapeIdentifier'), $mixIdentifiers);
 456:             } else {
 457:                 return $this->EscapeIdentifier($mixIdentifiers);
 458:             }
 459:         }
 460: 
 461:         /**
 462:          * Escapes values (or single value) which we can then send to the database
 463:          *
 464:          * @param array|mixed $mixValues Array of values (or a single value) to be escaped
 465:          *
 466:          * @return array|string Array of (or a single) escaped value(s)
 467:          */
 468:         public function EscapeValues($mixValues) {
 469:             if (is_array($mixValues)) {
 470:                 return array_map(array($this, 'SqlVariable'), $mixValues);
 471:             } else {
 472:                 return $this->SqlVariable($mixValues);
 473:             }
 474:         }
 475: 
 476:         /**
 477:          * Escapes both column and values when supplied as an array
 478:          *
 479:          * @param array $mixColumnsAndValuesArray Array with column=>value format with both (column and value) sides unescaped
 480:          *
 481:          * @return array Array with column=>value format data with both column and value escaped
 482:          */
 483:         public function EscapeIdentifiersAndValues($mixColumnsAndValuesArray) {
 484:             $result = array();
 485:             foreach ($mixColumnsAndValuesArray as $strColumn => $mixValue) {
 486:                 $result[$this->EscapeIdentifier($strColumn)] = $this->SqlVariable($mixValue);
 487:             }
 488:             return $result;
 489:         }
 490: 
 491:         /**
 492:          * INSERTs or UPDATEs a table
 493:          *
 494:          * @param string            $strTable                 Table name
 495:          * @param array             $mixColumnsAndValuesArray column=>value array
 496:          *                                                    (they are given to 'EscapeIdentifiersAndValues' method)
 497:          * @param null|string|array $strPKNames               Name(s) of primary key column(s) (expressed as string or array)
 498:          */
 499:         public function InsertOrUpdate($strTable, $mixColumnsAndValuesArray, $strPKNames = null) {
 500:             $strEscapedArray = $this->EscapeIdentifiersAndValues($mixColumnsAndValuesArray);
 501:             $strColumns = array_keys($strEscapedArray);
 502:             $strUpdateStatement = '';
 503:             foreach ($strEscapedArray as $strColumn => $strValue) {
 504:                 if ($strUpdateStatement) $strUpdateStatement .= ', ';
 505:                 $strUpdateStatement .= $strColumn . ' = ' . $strValue;
 506:             }
 507:             if (is_null($strPKNames)) {
 508:                 $strMatchCondition = 'target_.'.$strColumns[0].' = source_.'.$strColumns[0];
 509:             } else if (is_array($strPKNames)) {
 510:                 $strMatchCondition = '';
 511:                 foreach ($strPKNames as $strPKName) {
 512:                     if ($strMatchCondition) $strMatchCondition .= ' AND ';
 513:                     $strMatchCondition .= 'target_.'.$this->EscapeIdentifier($strPKName).' = source_.'.$this->EscapeIdentifier($strPKName);
 514:                 }
 515:             } else {
 516:                 $strMatchCondition = 'target_.'.$this->EscapeIdentifier($strPKNames).' = source_.'.$this->EscapeIdentifier($strPKNames);
 517:             }
 518:             $strTable = $this->EscapeIdentifierBegin . $strTable . $this->EscapeIdentifierEnd;
 519:             $strSql = sprintf('MERGE INTO %s AS target_ USING %s AS source_ ON %s WHEN MATCHED THEN UPDATE SET %s WHEN NOT MATCHED THEN INSERT (%s) VALUES (%s)',
 520:                 $strTable, $strTable,
 521:                 $strMatchCondition, $strUpdateStatement,
 522:                 implode(', ', $strColumns),
 523:                 implode(', ', array_values($strEscapedArray))
 524:             );
 525:             $this->ExecuteNonQuery($strSql);
 526:         }
 527: 
 528:         /**
 529:          * Sends the 'SELECT' query to the database and returns the result
 530:          *
 531:          * @param string $strQuery query string
 532:          *
 533:          * @return QDatabaseResultBase
 534:          */
 535:         public final function Query($strQuery) {
 536:             $timerName = null;
 537:             if (!$this->blnConnectedFlag) {
 538:                 $this->Connect();
 539:             }
 540:             
 541:             
 542:             if ($this->blnEnableProfiling) {
 543:                 $timerName = 'queryExec' . mt_rand() ;
 544:                 QTimer::Start($timerName);
 545:             }
 546:             
 547:             $result = $this->ExecuteQuery($strQuery);
 548:             
 549:             if ($this->blnEnableProfiling) {
 550:                 $dblQueryTime = QTimer::Stop($timerName);
 551:                 QTimer::Reset($timerName);
 552:                 
 553:                 // Log Query (for Profiling, if applicable)
 554:                 $this->LogQuery($strQuery, $dblQueryTime);
 555:             }
 556: 
 557:             return $result;
 558:         }
 559: 
 560:         /**
 561:          * This is basically the same as 'Query' but is used when SQL statements other than 'SELECT'
 562:          * @param string $strNonQuery The SQL to be sent
 563:          *
 564:          * @return mixed
 565:          * @throws QCallerException
 566:          */
 567:         public final function NonQuery($strNonQuery) {
 568:             if (!$this->blnConnectedFlag) {
 569:                 $this->Connect();
 570:             }
 571:             $timerName = '';
 572:             if ($this->blnEnableProfiling) {
 573:                 $timerName = 'queryExec' . mt_rand() ;
 574:                 QTimer::Start($timerName);
 575:             }
 576:             
 577:             $result = $this->ExecuteNonQuery($strNonQuery);
 578: 
 579:             if ($this->blnEnableProfiling) {
 580:                 $dblQueryTime = QTimer::Stop($timerName);
 581:                 QTimer::Reset($timerName);
 582:     
 583:                 // Log Query (for Profiling, if applicable)
 584:                 $this->LogQuery($strNonQuery, $dblQueryTime);
 585:             }
 586:             
 587:             return $result;
 588:         }
 589: 
 590:         /**
 591:          * PHP magic method
 592:          * @param string $strName Property name
 593:          *
 594:          * @return mixed
 595:          * @throws Exception|QCallerException
 596:          */
 597:         public function __get($strName) {
 598:             switch ($strName) {
 599:                 case 'EscapeIdentifierBegin':
 600:                     return $this->strEscapeIdentifierBegin;
 601:                 case 'EscapeIdentifierEnd':
 602:                     return $this->strEscapeIdentifierEnd;
 603:                 case 'EnableProfiling':
 604:                     return $this->blnEnableProfiling;
 605:                 case 'AffectedRows':
 606:                     return -1;
 607:                 case 'Profile':
 608:                     return $this->strProfileArray;
 609:                 case 'DatabaseIndex':
 610:                     return $this->intDatabaseIndex;                 
 611:                 case 'Adapter':
 612:                     $strConstantName = get_class($this) . '::Adapter';
 613:                     return constant($strConstantName) . ' (' . $this->objConfigArray['adapter'] . ')';
 614:                 case 'Server':
 615:                 case 'Port':
 616:                 case 'Database':
 617:                 // Informix naming
 618:                 case 'Service':
 619:                 case 'Protocol':
 620:                 case 'Host':
 621:                 
 622:                 case 'Username':
 623:                 case 'Password':
 624:                 case 'Caching':
 625:                     return $this->objConfigArray[strtolower($strName)];
 626:                 case 'DateFormat':
 627:                     return (is_null($this->objConfigArray[strtolower($strName)])) ? (QDateTime::FormatIso) : ($this->objConfigArray[strtolower($strName)]);
 628:                 case 'OnlyFullGroupBy':
 629:                     return (!isset($this->objConfigArray[strtolower($strName)])) ? $this->blnOnlyFullGroupBy : $this->objConfigArray[strtolower($strName)];
 630: 
 631:                 default:
 632:                     try {
 633:                         return parent::__get($strName);
 634:                     } catch (QCallerException $objExc) {
 635:                         $objExc->IncrementOffset();
 636:                         throw $objExc;
 637:                     }
 638:             }
 639:         }
 640: 
 641:         /**
 642:          * PHP magic method to set class properties
 643:          * @param string $strName  Property name
 644:          * @param string $mixValue Property value
 645:          *
 646:          * @return mixed|void
 647:          * @throws Exception|QCallerException
 648:          */
 649:         public function __set($strName, $mixValue) {
 650:             switch ($strName) {
 651:                 case 'Caching':
 652:                     $this->objConfigArray[strtolower($strName)] = $mixValue;
 653:                     break;
 654: 
 655:                 default:
 656:                     try {
 657:                         parent::__set($strName, $mixValue);
 658:                     } catch (QCallerException $objExc) {
 659:                         $objExc->IncrementOffset();
 660:                         throw $objExc;
 661:                     }
 662:             }
 663:         }
 664: 
 665:         /**
 666:          * Constructs a Database Adapter based on the database index and the configuration array of properties
 667:          * for this particular adapter. Sets up the base-level configuration properties for this database,
 668:          * namely DB Profiling and Database Index
 669:          *
 670:          * @param integer  $intDatabaseIndex
 671:          * @param string[] $objConfigArray configuration array as passed in to the constructor
 672:          *                                 by QApplicationBase::InitializeDatabaseConnections();
 673:          *
 674:          * @throws Exception|QCallerException|QInvalidCastException
 675:          * @return QDatabaseBase
 676:          */
 677:         public function __construct($intDatabaseIndex, $objConfigArray) {
 678:             // Setup DatabaseIndex
 679:             $this->intDatabaseIndex = $intDatabaseIndex;
 680: 
 681:             // Save the ConfigArray
 682:             $this->objConfigArray = $objConfigArray;
 683: 
 684:             // Setup Profiling Array (if applicable)
 685:             $this->blnEnableProfiling = QType::Cast($objConfigArray['profiling'], QType::Boolean);
 686:             if ($this->blnEnableProfiling)
 687:                 $this->strProfileArray = array();
 688:         }
 689: 
 690:         /**
 691:          * Allows for the enabling of DB profiling while in middle of the script
 692:          *
 693:          * @return void
 694:          */
 695:         public function EnableProfiling() {
 696:             // Only perform profiling initialization if profiling is not yet enabled
 697:             if (!$this->blnEnableProfiling) {
 698:                 $this->blnEnableProfiling = true;
 699:                 $this->strProfileArray = array();
 700:             }
 701:         }
 702: 
 703:         /**
 704:          * If EnableProfiling is on, then log the query to the profile array
 705:          *
 706:          * @param string $strQuery
 707:          * @param double $dblQueryTime query execution time in milliseconds
 708:          * @return void
 709:          */
 710:         private function LogQuery($strQuery, $dblQueryTime) {
 711:             if ($this->blnEnableProfiling) {
 712:                 // Dereference-ize Backtrace Information
 713:                 $objDebugBacktrace = debug_backtrace();
 714:                 
 715:                 // get rid of unnecessary backtrace info in case of:
 716:                 // query
 717:                 if ((count($objDebugBacktrace) > 3) &&
 718:                     (array_key_exists('function', $objDebugBacktrace[2])) &&
 719:                     (($objDebugBacktrace[2]['function'] == 'QueryArray') ||
 720:                      ($objDebugBacktrace[2]['function'] == 'QuerySingle') ||
 721:                      ($objDebugBacktrace[2]['function'] == 'QueryCount')))
 722:                     $objBacktrace = $objDebugBacktrace[3];
 723:                 else
 724:                     if (isset($objDebugBacktrace[2]))
 725:                         // non query
 726:                         $objBacktrace = $objDebugBacktrace[2];
 727:                     else
 728:                         // ad hoc query
 729:                         $objBacktrace = $objDebugBacktrace[1];
 730:                 
 731:                 // get rid of reference to current object in backtrace array
 732:                 if( isset($objBacktrace['object']))
 733:                     $objBacktrace['object'] = null;
 734:                 
 735:                 for ($intIndex = 0, $intMax = count($objBacktrace['args']); $intIndex < $intMax; $intIndex++) {
 736:                     $obj = $objBacktrace['args'][$intIndex];
 737:                     if (($obj instanceof QQClause) || ($obj instanceof QQCondition))
 738:                         $obj = sprintf("[%s]", $obj->__toString());
 739:                     else if (is_null($obj))
 740:                         $obj = 'null';
 741:                     else if (gettype($obj) == 'integer') {}
 742:                     else if (gettype($obj) == 'object')
 743:                         $obj = 'Object';
 744:                     else if (is_array($obj))
 745:                         $obj = 'Array';
 746:                     else
 747:                         $obj = sprintf("'%s'", $obj);
 748:                     $objBacktrace['args'][$intIndex] = $obj;
 749:                 }
 750:                 
 751:                 // Push it onto the profiling information array
 752:                 $arrProfile = array(
 753:                     'objBacktrace'  => $objBacktrace,
 754:                     'strQuery'          => $strQuery,
 755:                     'dblTimeInfo'       => $dblQueryTime);
 756:                 
 757:                 array_push( $this->strProfileArray, $arrProfile);
 758:             }
 759:         }
 760: 
 761:         /**
 762:          * Properly escapes $mixData to be used as a SQL query parameter.
 763:          * If IncludeEquality is set (usually not), then include an equality operator.
 764:          * So for most data, it would just be "=".  But, for example,
 765:          * if $mixData is NULL, then most RDBMS's require the use of "IS".
 766:          *
 767:          * @param mixed $mixData
 768:          * @param boolean $blnIncludeEquality whether or not to include an equality operator
 769:          * @param boolean $blnReverseEquality whether the included equality operator should be a "NOT EQUAL", e.g. "!="
 770:          * @return string the properly formatted SQL variable
 771:          */
 772:         public function SqlVariable($mixData, $blnIncludeEquality = false, $blnReverseEquality = false) {
 773:             // Are we SqlVariabling a BOOLEAN value?
 774:             if (is_bool($mixData)) {
 775:                 // Yes
 776:                 if ($blnIncludeEquality) {
 777:                     // We must include the inequality
 778: 
 779:                     if ($blnReverseEquality) {
 780:                         // Do a "Reverse Equality"
 781: 
 782:                         // Check against NULL, True then False
 783:                         if (is_null($mixData))
 784:                             return 'IS NOT NULL';
 785:                         else if ($mixData)
 786:                             return '= 0';
 787:                         else
 788:                             return '!= 0';
 789:                     } else {
 790:                         // Check against NULL, True then False
 791:                         if (is_null($mixData))
 792:                             return 'IS NULL';
 793:                         else if ($mixData)
 794:                             return '!= 0';
 795:                         else
 796:                             return '= 0';
 797:                     }
 798:                 } else {
 799:                     // Check against NULL, True then False
 800:                     if (is_null($mixData))
 801:                         return 'NULL';
 802:                     else if ($mixData)
 803:                         return '1';
 804:                     else
 805:                         return '0';
 806:                 }
 807:             }
 808: 
 809:             // Check for Equality Inclusion
 810:             if ($blnIncludeEquality) {
 811:                 if ($blnReverseEquality) {
 812:                     if (is_null($mixData))
 813:                         $strToReturn = 'IS NOT ';
 814:                     else
 815:                         $strToReturn = '!= ';
 816:                 } else {
 817:                     if (is_null($mixData))
 818:                         $strToReturn = 'IS ';
 819:                     else
 820:                         $strToReturn = '= ';
 821:                 }
 822:             } else
 823:                 $strToReturn = '';
 824: 
 825:             // Check for NULL Value
 826:             if (is_null($mixData))
 827:                 return $strToReturn . 'NULL';
 828: 
 829:             // Check for NUMERIC Value
 830:             if (is_integer($mixData) || is_float($mixData))
 831:                 return $strToReturn . sprintf('%s', $mixData);
 832: 
 833:             // Check for DATE Value
 834:             if ($mixData instanceof QDateTime) {
 835:                 /** @var QDateTime $mixData */
 836:                 if ($mixData->IsTimeNull()) {
 837:                     if ($mixData->IsDateNull()) {
 838:                         return $strToReturn . 'NULL'; // null date and time is a null value
 839:                     }
 840:                     return $strToReturn . sprintf("'%s'", $mixData->qFormat('YYYY-MM-DD'));
 841:                 }
 842:                 elseif ($mixData->IsDateNull()) {
 843:                     return  $strToReturn . sprintf("'%s'", $mixData->qFormat('hhhh:mm:ss'));
 844:                 }
 845:                 return $strToReturn . sprintf("'%s'", $mixData->qFormat(QDateTime::FormatIso));
 846:             }
 847: 
 848:             // an array. Assume we are using it in an array context, like an IN clause
 849:             if (is_array($mixData)) {
 850:                 $items = [];
 851:                 foreach ($mixData as $item) {
 852:                     $items[] = $this->SqlVariable($item);   // recurse
 853:                 }
 854:                 return '(' . implode(',', $items) . ')';
 855:             }
 856: 
 857:             // Assume it's some kind of string value
 858:             return $strToReturn . sprintf("'%s'", addslashes($mixData));
 859:         }
 860: 
 861:         public function PrepareStatement($strQuery, $mixParameterArray) {
 862:             foreach ($mixParameterArray as $strKey => $mixValue) {
 863:                 if (is_array($mixValue)) {
 864:                     $strParameters = array();
 865:                     foreach ($mixValue as $mixParameter)
 866:                         array_push($strParameters, $this->SqlVariable($mixParameter));
 867:                     $strQuery = str_replace(chr(QQNamedValue::DelimiterCode) . '{' . $strKey . '}', implode(',', $strParameters) . ')', $strQuery);
 868:                 } else {
 869:                     $strQuery = str_replace(chr(QQNamedValue::DelimiterCode) . '{=' . $strKey . '=}', $this->SqlVariable($mixValue, true, false), $strQuery);
 870:                     $strQuery = str_replace(chr(QQNamedValue::DelimiterCode) . '{!' . $strKey . '!}', $this->SqlVariable($mixValue, true, true), $strQuery);
 871:                     $strQuery = str_replace(chr(QQNamedValue::DelimiterCode) . '{' . $strKey . '}', $this->SqlVariable($mixValue), $strQuery);
 872:                 }
 873:             }
 874: 
 875:             return $strQuery;
 876:         }
 877: 
 878:         /**
 879:          * Displays the OutputProfiling results, plus a link which will popup the details of the profiling.
 880:          *
 881:          * @param bool $blnPrintOutput
 882:          * @return null|string
 883:          */
 884:         public function OutputProfiling($blnPrintOutput = true) {
 885: 
 886:             $strOut = '<div class="qDbProfile">';
 887:             if ($this->blnEnableProfiling) {
 888:                 $strOut .= sprintf('<form method="post" id="frmDbProfile%s" action="%s/profile.php"><div>',
 889:                     $this->intDatabaseIndex, __VIRTUAL_DIRECTORY__ . __PHP_ASSETS__);
 890:                 $strOut.= sprintf('<input type="hidden" name="strProfileData" value="%s" />',
 891:                     base64_encode(serialize($this->strProfileArray)));
 892:                 $strOut .= sprintf('<input type="hidden" name="intDatabaseIndex" value="%s" />', $this->intDatabaseIndex);
 893:                 $strOut .= sprintf('<input type="hidden" name="strReferrer" value="%s" /></div></form>', QApplication::HtmlEntities(QApplication::$RequestUri));
 894: 
 895:                 $intCount = round(count($this->strProfileArray));
 896:                 if ($intCount == 0)
 897:                     $strQueryString =  'No queries';
 898:                 else if ($intCount == 1)
 899:                     $strQueryString =  '1 query';
 900:                 else
 901:                     $strQueryString =  $intCount . ' queries';
 902: 
 903:                 $strOut .= sprintf('<b>PROFILING INFORMATION FOR DATABASE CONNECTION #%s</b>: %s performed.  Please <a href="#" onclick="var frmDbProfile = document.getElementById(\'frmDbProfile%s\'); frmDbProfile.target = \'_blank\'; frmDbProfile.submit(); return false;">click here to view profiling detail</a><br />',
 904:                     $this->intDatabaseIndex, $strQueryString, $this->intDatabaseIndex);
 905:             } else {
 906:                 $strOut .= '<form></form><b>Profiling was not enabled for this database connection (#' . $this->intDatabaseIndex . ').</b>  To enable, ensure that ENABLE_PROFILING is set to TRUE.';
 907:             }
 908:             $strOut .= '</div>';
 909: 
 910:             $strOut .= '<script>$j(function() {$j(".qDbProfile").draggable();});</script>'; // make it draggable so you can move it out of the way if needed.
 911: 
 912:             if ($blnPrintOutput) {
 913:                 print ($strOut);
 914:                 return null;
 915:             }
 916:             else {
 917:                 return $strOut;
 918:             }
 919:         }
 920: 
 921:         /**
 922:          * Executes the explain statement for a given query and returns the output without any transformation.
 923:          * If the database adapter does not support EXPLAIN statements, returns null.
 924:          *
 925:          * @param $strSql
 926:          *
 927:          * @return null
 928:          */
 929:         public function ExplainStatement($strSql) {
 930:             return null;
 931:         }
 932: 
 933: 
 934:         /**
 935:          * Utility function to extract the json embedded options structure from the comments.
 936:          *
 937:          * Usage:
 938:          * <code>
 939:          *  list($strComment, $options) = QDatabaseFieldBase::ExtractCommentOptions($strComment);
 940:          * </code>
 941:          *
 942:          * @param string $strComment    The comment to analyze
 943:          * @return array A two item array, with first item the comment with the options removed, and 2nd item the options array.
 944:          *
 945:          */
 946:         public static function ExtractCommentOptions($strComment) {
 947:             $ret[0] = null; // comment string without options
 948:             $ret[1] = null; // the options array
 949:             if (($strComment) &&
 950:                 ($pos1 = strpos ($strComment, '{')) !== false &&
 951:                 ($pos2 = strrpos ($strComment, '}', $pos1))) {
 952: 
 953:                 $strJson = substr ($strComment, $pos1, $pos2 - $pos1 + 1);
 954:                 $a = json_decode($strJson, true);
 955: 
 956:                 if ($a) {
 957:                     $ret[0] = substr ($strComment, 0, $pos1) . substr ($strComment, $pos2 + 1); // return comment without options
 958:                     $ret[1] = $a;
 959:                 } else {
 960:                     $ret[0] = $strComment;
 961:                 }
 962:             }
 963: 
 964:             return $ret;
 965:         }
 966: 
 967:     }
 968: 
 969:     abstract class QDatabaseFieldBase extends QBaseClass {
 970:         protected $strName;
 971:         protected $strOriginalName;
 972:         protected $strTable;
 973:         protected $strOriginalTable;
 974:         protected $strDefault;
 975:         protected $intMaxLength;
 976:         protected $strComment;
 977: 
 978:         // Bool
 979:         protected $blnIdentity;
 980:         protected $blnNotNull;
 981:         protected $blnPrimaryKey;
 982:         protected $blnUnique;
 983:         protected $blnTimestamp;
 984: 
 985:         protected $strType;
 986: 
 987:         /**
 988:          * PHP magic method
 989:          *
 990:          * @param string $strName Property name
 991:          *
 992:          * @return mixed
 993:          * @throws Exception|QCallerException
 994:          */
 995:         public function __get($strName) {
 996:             switch ($strName) {
 997:                 case "Name":
 998:                     return $this->strName;
 999:                 case "OriginalName":
1000:                     return $this->strOriginalName;
1001:                 case "Table":
1002:                     return $this->strTable;
1003:                 case "OriginalTable":
1004:                     return $this->strOriginalTable;
1005:                 case "Default":
1006:                     return $this->strDefault;
1007:                 case "MaxLength":
1008:                     return $this->intMaxLength;
1009:                 case "Identity":
1010:                     return $this->blnIdentity;
1011:                 case "NotNull":
1012:                     return $this->blnNotNull;
1013:                 case "PrimaryKey":
1014:                     return $this->blnPrimaryKey;
1015:                 case "Unique":
1016:                     return $this->blnUnique;
1017:                 case "Timestamp":
1018:                     return $this->blnTimestamp;
1019:                 case "Type":
1020:                     return $this->strType;
1021:                 case "Comment":
1022:                     return $this->strComment;
1023:                 default:
1024:                     try {
1025:                         return parent::__get($strName);
1026:                     } catch (QCallerException $objExc) {
1027:                         $objExc->IncrementOffset();
1028:                         throw $objExc;
1029:                     }
1030:             }
1031:         }
1032:     }
1033: 
1034:     /**
1035:      * Class to handle results sent by database upon querying
1036:      * @property QQueryBuilder $QueryBuilder
1037:      */
1038:     abstract class QDatabaseResultBase extends QBaseClass {
1039:         // Allow to attach a QQueryBuilder object to use the result object as cursor resource for cursor queries.
1040:         /** @var QQueryBuilder Query builder object */
1041:         protected $objQueryBuilder;
1042: 
1043:         /**
1044:          * Fetches one row as indexed (column=>value style) array from the result set
1045:          * @abstract
1046:          * @return mixed
1047:          */
1048:         abstract public function FetchArray();
1049: 
1050:         /**
1051:          * Fetches one row as enumerated (with numerical indexes) array from the result set
1052:          * @abstract
1053:          * @return mixed
1054:          */
1055:         abstract public function FetchRow();
1056: 
1057:         abstract public function FetchField();
1058:         abstract public function FetchFields();
1059:         abstract public function CountRows();
1060:         abstract public function CountFields();
1061: 
1062:         abstract public function GetNextRow();
1063:         abstract public function GetRows();
1064: 
1065:         abstract public function Close();
1066: 
1067:         /**
1068:          * PHP magic method
1069:          *
1070:          * @param string $strName Property name
1071:          *
1072:          * @return mixed
1073:          * @throws Exception|QCallerException
1074:          */
1075:         public function __get($strName) {
1076:             switch ($strName) {
1077:                 case 'QueryBuilder':
1078:                     return $this->objQueryBuilder;
1079:                 default:
1080:                     try {
1081:                         return parent::__get($strName);
1082:                     } catch (QCallerException $objExc) {
1083:                         $objExc->IncrementOffset();
1084:                         throw $objExc;
1085:                     }
1086:             }
1087:         }
1088: 
1089:         public function __set($strName, $mixValue) {
1090:             switch ($strName) {
1091:                 case 'QueryBuilder':
1092:                     try {
1093:                         return ($this->objQueryBuilder = QType::Cast($mixValue, 'QQueryBuilder'));
1094:                     } catch (QInvalidCastException $objExc) {
1095:                         $objExc->IncrementOffset();
1096:                         throw $objExc;
1097:                     }
1098:                 default:
1099:                     try {
1100:                         return parent::__set($strName, $mixValue);
1101:                     } catch (QCallerException $objExc) {
1102:                         $objExc->IncrementOffset();
1103:                         throw $objExc;
1104:                     }
1105:             }
1106:         }
1107:     }
1108:     
1109:     /**
1110:      * Base class for all Database rows. Implemented by Database adapters
1111:      * @package DatabaseAdapters
1112:      */
1113:     abstract class QDatabaseRowBase extends QBaseClass {
1114:         /**
1115:          * Gets the value of a column from a result row returned by the database
1116:          *
1117:          * @param string      $strColumnName Name of the column
1118:          * @param null|string $strColumnType Data type
1119:          *
1120:          * @return mixed
1121:          */
1122:         abstract public function GetColumn($strColumnName, $strColumnType = null);
1123:         /**
1124:          * Tells whether a particular column exists in a returned database row
1125:          *
1126:          * @param string $strColumnName Name of te column
1127:          *
1128:          * @return bool
1129:          */
1130:         abstract public function ColumnExists($strColumnName);
1131:         abstract public function GetColumnNameArray();
1132: 
1133:         /**
1134:          * Returns the boolean value corresponding to whatever a boolean column returns. Some database types
1135:          * return strings that represent the boolean values. Default is to use a PHP cast.
1136:          * @param $mixValue Value of the BIT column
1137:          * @return bool
1138:          */
1139:         public function ResolveBooleanValue ($mixValue) {
1140:             if ($mixValue === null) {
1141:                 return null;
1142:             }
1143:             return ((bool)$mixValue);
1144:         }
1145: 
1146:     }
1147: 
1148:     /**
1149:      * Class to handle exceptions related to database querying
1150:      * @property-read int $ErrorNumber The number of error provided by the SQL server
1151:      * @property-read string $Query The query caused the error
1152:      * @package DatabaseAdapters
1153:      */
1154:     abstract class QDatabaseExceptionBase extends QCallerException {
1155:         /** @var int Error number */
1156:         protected $intErrorNumber;
1157:         /** @var string Query which produced the error */
1158:         protected $strQuery;
1159: 
1160:         /**
1161:          * PHP magic function to get property values
1162:          * @param string $strName
1163:          *
1164:          * @return array|int|mixed
1165:          */
1166:         public function __get($strName) {
1167:             switch ($strName) {
1168:                 case "ErrorNumber":
1169:                     return $this->intErrorNumber;
1170:                 case "Query";
1171:                     return $this->strQuery;
1172:                 default:
1173:                     return parent::__get($strName);
1174:             }
1175:         }
1176:     }
1177: 
1178:     /**
1179:      *
1180:      * @package DatabaseAdapters
1181:      */
1182:     class QDatabaseForeignKey extends QBaseClass {
1183:         protected $strKeyName;
1184:         protected $strColumnNameArray;
1185:         protected $strReferenceTableName;
1186:         protected $strReferenceColumnNameArray;
1187: 
1188:         public function __construct($strKeyName, $strColumnNameArray, $strReferenceTableName, $strReferenceColumnNameArray) {
1189:             $this->strKeyName = $strKeyName;
1190:             $this->strColumnNameArray = $strColumnNameArray;
1191:             $this->strReferenceTableName = $strReferenceTableName;
1192:             $this->strReferenceColumnNameArray = $strReferenceColumnNameArray;
1193:         }
1194: 
1195:         /**
1196:          * PHP magic method
1197:          *
1198:          * @param string $strName Property name
1199:          *
1200:          * @return mixed
1201:          * @throws Exception|QCallerException
1202:          */
1203:         public function __get($strName) {
1204:             switch ($strName) {
1205:                 case "KeyName":
1206:                     return $this->strKeyName;
1207:                 case "ColumnNameArray":
1208:                     return $this->strColumnNameArray;
1209:                 case "ReferenceTableName":
1210:                     return $this->strReferenceTableName;
1211:                 case "ReferenceColumnNameArray":
1212:                     return $this->strReferenceColumnNameArray;
1213:                 default:
1214:                     try {
1215:                         return parent::__get($strName);
1216:                     } catch (QCallerException $objExc) {
1217:                         $objExc->IncrementOffset();
1218:                         throw $objExc;
1219:                     }
1220:             }
1221:         }
1222:     }
1223: 
1224:     /**
1225:      * To handle index in a table in database
1226:      * @package DatabaseAdapters
1227:      */
1228:     class QDatabaseIndex extends QBaseClass {
1229:         /** @var string Name of the index */
1230:         protected $strKeyName;
1231:         /** @var bool Is the Index a primary key index? */
1232:         protected $blnPrimaryKey;
1233:         /** @var bool Is this a Unique index? */
1234:         protected $blnUnique;
1235:         /** @var array Array of column names on which this index is defined */
1236:         protected $strColumnNameArray;
1237: 
1238:         /**
1239:          * @param string $strKeyName         Name of the index
1240:          * @param string $blnPrimaryKey      Is this index a Primary key index?
1241:          * @param string $blnUnique          Is this index unique?
1242:          * @param array  $strColumnNameArray Columns on which this index is defined
1243:          */
1244:         public function __construct($strKeyName, $blnPrimaryKey, $blnUnique, $strColumnNameArray) {
1245:             $this->strKeyName = $strKeyName;
1246:             $this->blnPrimaryKey = $blnPrimaryKey;
1247:             $this->blnUnique = $blnUnique;
1248:             $this->strColumnNameArray = $strColumnNameArray;
1249:         }
1250: 
1251:         /**
1252:          * PHP magic function
1253:          * @param string $strName
1254:          *
1255:          * @return mixed
1256:          * @throws Exception|QCallerException
1257:          */
1258:         public function __get($strName) {
1259:             switch ($strName) {
1260:                 case "KeyName":
1261:                     return $this->strKeyName;
1262:                 case "PrimaryKey":
1263:                     return $this->blnPrimaryKey;
1264:                 case "Unique":
1265:                     return $this->blnUnique;
1266:                 case "ColumnNameArray":
1267:                     return $this->strColumnNameArray;
1268:                 default:
1269:                     try {
1270:                         return parent::__get($strName);
1271:                     } catch (QCallerException $objExc) {
1272:                         $objExc->IncrementOffset();
1273:                         throw $objExc;
1274:                     }
1275:             }
1276:         }
1277:     }
1278: 
1279:     /**
1280:      * Data types in a database
1281:      * @package DatabaseAdapters
1282:      */
1283:     abstract class QDatabaseFieldType {
1284:         /** Binary Data (Binary Large OBjects/BLOBs) */
1285:         const Blob = "Blob";
1286:         /** Character sequence - variable length */
1287:         const VarChar = "VarChar";
1288:         /** Character sequence - fixed length */
1289:         const Char = "Char";
1290:         /** Integers */
1291:         const Integer = "Integer";
1292:         /** Date and Time together */
1293:         const DateTime = "DateTime";
1294:         /** Date only */
1295:         const Date = "Date";
1296:         /** Time only */
1297:         const Time = "Time";
1298:         /** Float, Double and real (postgresql) */
1299:         const Float = "Float";
1300:         /** Boolean */
1301:         const Bit = "Bit";
1302:         /** New JSON type */
1303:         const Json = "Json";
1304:     }
API documentation generated by ApiGen