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:     require(__QCUBED_CORE__ . '/codegen/QSqlColumn.class.php');
   3:     require(__QCUBED_CORE__ . '/codegen/QIndex.class.php');
   4:     require(__QCUBED_CORE__ . '/codegen/QManyToManyReference.class.php');
   5:     require(__QCUBED_CORE__ . '/codegen/QReference.class.php');
   6:     require(__QCUBED_CORE__ . '/codegen/QReverseReference.class.php');
   7:     require(__QCUBED_CORE__ . '/codegen/QSqlTable.class.php');
   8:     require(__QCUBED_CORE__ . '/codegen/QTypeTable.class.php');
   9:     require(__QCUBED_CORE__ . '/codegen/QModelConnectorOptions.class.php');
  10: 
  11:     /**
  12:      * @package Codegen
  13:      */
  14:     class QDatabaseCodeGen extends QCodeGen {
  15:         public $objSettingsXml; // Make public so templates can use it directly.
  16: 
  17:         // Objects
  18:         /** @var array|QSqlTable[] Array of tables in the database */
  19:         protected $objTableArray;
  20:         protected $strExcludedTableArray;
  21:         protected $objTypeTableArray;
  22:         protected $strAssociationTableNameArray;
  23:         /** @var QDatabaseBase The database we are dealing with */
  24:         protected $objDb;
  25: 
  26:         protected $intDatabaseIndex;
  27:         /** @var string The delimiter to be used for parsing comments on the DB tables for being used as the name of ModelConnector's Label */
  28:         protected $strCommentConnectorLabelDelimiter;
  29: 
  30:         // Table Suffixes
  31:         protected $strTypeTableSuffixArray;
  32:         protected $intTypeTableSuffixLengthArray;
  33:         protected $strAssociationTableSuffix;
  34:         protected $intAssociationTableSuffixLength;
  35: 
  36:         // Table Prefix
  37:         protected $strStripTablePrefix;
  38:         protected $intStripTablePrefixLength;
  39: 
  40:         // Exclude Patterns & Lists
  41:         protected $strExcludePattern;
  42:         protected $strExcludeListArray;
  43: 
  44:         // Include Patterns & Lists
  45:         protected $strIncludePattern;
  46:         protected $strIncludeListArray;
  47: 
  48:         // Uniquely Associated Objects
  49:         protected $strAssociatedObjectPrefix;
  50:         protected $strAssociatedObjectSuffix;
  51: 
  52:         // Manual Query (e.g. "Beta 2 Query") Suppor
  53:         protected $blnManualQuerySupport = false;
  54: 
  55:         // Relationship Scripts
  56:         protected $strRelationships;
  57:         protected $blnRelationshipsIgnoreCase;
  58: 
  59:         protected $strRelationshipsScriptPath;
  60:         protected $strRelationshipsScriptFormat;
  61:         protected $blnRelationshipsScriptIgnoreCase;
  62: 
  63:         protected $strRelationshipLinesQcubed = array();
  64:         protected $strRelationshipLinesSql = array();
  65: 
  66:         // Type Table Items, Table Name and Column Name RegExp Patterns
  67:         protected $strPatternTableName = '[[:alpha:]_][[:alnum:]_]*';
  68:         protected $strPatternColumnName = '[[:alpha:]_][[:alnum:]_]*';
  69:         protected $strPatternKeyName = '[[:alpha:]_][[:alnum:]_]*';
  70: 
  71:         protected $blnGenerateControlId;
  72:         protected $objModelConnectorOptions;
  73:         protected $blnAutoInitialize;
  74: 
  75:         /**
  76:          * @param $strTableName
  77:          * @return QSqlTable|QTypeTable
  78:          * @throws QCallerException
  79:          */
  80:         public function GetTable($strTableName) {
  81:             $strTableName = strtolower($strTableName);
  82:             if (array_key_exists($strTableName, $this->objTableArray))
  83:                 return $this->objTableArray[$strTableName];
  84:             if (array_key_exists($strTableName, $this->objTypeTableArray)) 
  85:                 return $this->objTypeTableArray[$strTableName];;    // deal with table special
  86:             throw new QCallerException(sprintf('Table does not exist or does not have a defined Primary Key: %s', $strTableName));
  87:         }
  88: 
  89:         public function GetColumn($strTableName, $strColumnName) {
  90:             try {
  91:                 $objTable = $this->GetTable($strTableName);
  92:             } catch (QCallerException $objExc) {
  93:                 $objExc->IncrementOffset();
  94:                 throw $objExc;
  95:             }
  96:             $strColumnName = strtolower($strColumnName);
  97:             if (array_key_exists($strColumnName, $objTable->ColumnArray))
  98:                 return $objTable->ColumnArray[$strColumnName];
  99:             throw new QCallerException(sprintf('Column does not exist in %s: %s', $strTableName, $strColumnName));
 100:         }
 101: 
 102:         /**
 103:          * Given a CASE INSENSITIVE table and column name, it will return TRUE if the Table/Column
 104:          * exists ANYWHERE in the already analyzed database
 105:          *
 106:          * @param string $strTableName
 107:          * @param string $strColumnName
 108:          * @return boolean true if it is found/validated
 109:          */
 110:         public function ValidateTableColumn($strTableName, $strColumnName) {
 111:             $strTableName = trim(strtolower($strTableName));
 112:             $strColumnName = trim(strtolower($strColumnName));
 113: 
 114:             if (array_key_exists($strTableName, $this->objTableArray))
 115:                 $strTableName = $this->objTableArray[$strTableName]->Name;
 116:             else if (array_key_exists($strTableName, $this->objTypeTableArray))
 117:                 $strTableName = $this->objTypeTableArray[$strTableName]->Name;
 118:             else if (array_key_exists($strTableName, $this->strAssociationTableNameArray))
 119:                 $strTableName = $this->strAssociationTableNameArray[$strTableName];
 120:             else
 121:                 return false;
 122: 
 123:             $objFieldArray = $this->objDb->GetFieldsForTable($strTableName);
 124: 
 125:             foreach ($objFieldArray as $objField) {
 126:                 if (trim(strtolower($objField->Name)) == $strColumnName)
 127:                     return true;
 128:             }
 129: 
 130:             return false;
 131:         }
 132: 
 133:         public function GetTitle() {
 134:             if (!QApplication::$Database) {
 135:                 return '';
 136:             }
 137:             
 138:             if (array_key_exists($this->intDatabaseIndex, QApplication::$Database)) {
 139:                 $objDatabase = QApplication::$Database[$this->intDatabaseIndex];
 140:                 return sprintf('Database Index #%s (%s / %s / %s)', $this->intDatabaseIndex, $objDatabase->Adapter, $objDatabase->Server, $objDatabase->Database);
 141:             } else
 142:                 return sprintf('Database Index #%s (N/A)', $this->intDatabaseIndex);
 143:         }
 144: 
 145:         public function GetConfigXml() {
 146:             $strCrLf = "\r\n";
 147:             $strToReturn = sprintf('        <database index="%s">%s', $this->intDatabaseIndex, $strCrLf);
 148:             $strToReturn .= sprintf('           <className prefix="%s" suffix="%s"/>%s', $this->strClassPrefix, $this->strClassSuffix, $strCrLf);
 149:             $strToReturn .= sprintf('           <associatedObjectName prefix="%s" suffix="%s"/>%s', $this->strAssociatedObjectPrefix, $this->strAssociatedObjectSuffix, $strCrLf);
 150:             $strToReturn .= sprintf('           <typeTableIdentifier suffix="%s"/>%s', implode(',', $this->strTypeTableSuffixArray), $strCrLf);
 151:             $strToReturn .= sprintf('           <associationTableIdentifier suffix="%s"/>%s', $this->strAssociationTableSuffix, $strCrLf);
 152:             $strToReturn .= sprintf('           <stripFromTableName prefix="%s"/>%s', $this->strStripTablePrefix, $strCrLf);
 153:             $strToReturn .= sprintf('           <excludeTables pattern="%s" list="%s"/>%s', $this->strExcludePattern, implode(',', $this->strExcludeListArray), $strCrLf);
 154:             $strToReturn .= sprintf('           <includeTables pattern="%s" list="%s"/>%s', $this->strIncludePattern, implode(',', $this->strIncludeListArray), $strCrLf);
 155:             $strToReturn .= sprintf('           <manualQuery support="%s"/>%s', ($this->blnManualQuerySupport) ? 'true' : 'false', $strCrLf);
 156:             $strToReturn .= sprintf('           <relationships>%s', $strCrLf);
 157:             if ($this->strRelationships)
 158:                 $strToReturn .= sprintf('           %s%s', $this->strRelationships, $strCrLf);
 159:             $strToReturn .= sprintf('           </relationships>%s', $strCrLf);
 160:             $strToReturn .= sprintf('           <relationshipsScript filepath="%s" format="%s"/>%s', $this->strRelationshipsScriptPath, $this->strRelationshipsScriptFormat, $strCrLf);
 161:             $strToReturn .= sprintf('       </database>%s', $strCrLf);
 162:             return $strToReturn;
 163:         }
 164: 
 165:         public function GetReportLabel() {
 166:             // Setup Report Label
 167:             $intTotalTableCount = count($this->objTableArray) + count($this->objTypeTableArray);
 168:             if ($intTotalTableCount == 0)
 169:                 $strReportLabel = 'There were no tables available to attempt code generation.';
 170:             else if ($intTotalTableCount == 1)
 171:                 $strReportLabel = 'There was 1 table available to attempt code generation:';
 172:             else
 173:                 $strReportLabel = 'There were ' . $intTotalTableCount . ' tables available to attempt code generation:';
 174: 
 175:             return $strReportLabel;
 176:         }
 177: 
 178:         public function GenerateAll() {
 179:             $strReport = '';
 180: 
 181:             // Iterate through all the tables, generating one class at a time
 182:             if ($this->objTableArray) foreach ($this->objTableArray as $objTable) {
 183:                 if ($this->GenerateTable($objTable)) {
 184:                     $intCount = $objTable->ReferenceCount;
 185:                     if ($intCount == 0)
 186:                         $strCount = '(with no relationships)';
 187:                     else if ($intCount == 1)
 188:                         $strCount = '(with 1 relationship)';
 189:                     else
 190:                         $strCount = sprintf('(with %s relationships)', $intCount);
 191:                     $strReport .= sprintf("Successfully generated DB ORM Class:   %s %s\r\n", $objTable->ClassName, $strCount);
 192:                 } else
 193:                     $strReport .= sprintf("FAILED to generate DB ORM Class:       %s\r\n", $objTable->ClassName);
 194:             }
 195: 
 196:             // Iterate through all the TYPE tables, generating one TYPE class at a time
 197:             if ($this->objTypeTableArray) foreach ($this->objTypeTableArray as $objTypeTable) {
 198:                 if ($this->GenerateTypeTable($objTypeTable))
 199:                     $strReport .= sprintf("Successfully generated DB Type Class:  %s\n", $objTypeTable->ClassName);
 200:                 else
 201:                     $strReport .= sprintf("FAILED to generate DB Type class:      %s\n", $objTypeTable->ClassName);
 202:             }
 203: 
 204:             return $strReport;
 205:         }
 206: 
 207:         public static function GenerateAggregateHelper($objCodeGenArray) {
 208:             $strToReturn = array();
 209: 
 210:             if (count($objCodeGenArray)) {
 211:                 // Standard ORM Tables
 212:                 $objTableArray = array();
 213:                 foreach ($objCodeGenArray as $objCodeGen) {
 214:                     $objCurrentTableArray = $objCodeGen->TableArray;
 215:                     foreach ($objCurrentTableArray as $objTable)
 216:                         $objTableArray[$objTable->ClassName] = $objTable;
 217:                 }
 218: 
 219:                 $mixArgumentArray = array('objTableArray' => $objTableArray);
 220:                 if ($objCodeGenArray[0]->GenerateFiles('aggregate_db_orm', $mixArgumentArray))
 221:                     $strToReturn[] = 'Successfully generated Aggregate DB ORM file(s)';
 222:                 else
 223:                     $strToReturn[] = 'FAILED to generate Aggregate DB ORM file(s)';
 224: 
 225:                 // Type Tables
 226:                 $objTableArray = array();
 227:                 foreach ($objCodeGenArray as $objCodeGen) {
 228:                     $objCurrentTableArray = $objCodeGen->TypeTableArray;
 229:                     foreach ($objCurrentTableArray as $objTable)
 230:                         $objTableArray[$objTable->ClassName] = $objTable;
 231:                 }
 232: 
 233:                 $mixArgumentArray = array('objTableArray' => $objTableArray);
 234:                 if ($objCodeGenArray[0]->GenerateFiles('aggregate_db_type', $mixArgumentArray))
 235:                     $strToReturn[] = 'Successfully generated Aggregate DB Type file(s)';
 236:                 else
 237:                     $strToReturn[] = 'FAILED to generate Aggregate DB Type file(s)';
 238:             }
 239: 
 240:             return $strToReturn;
 241:         }
 242: 
 243:         public function __construct($objSettingsXml) {
 244:             parent::__construct($objSettingsXml);
 245:             // Make settings file accessible to templates
 246:             //$this->objSettingsXml = $objSettingsXml;
 247: 
 248:             // Setup Local Arrays
 249:             $this->strAssociationTableNameArray = array();
 250:             $this->objTableArray = array();
 251:             $this->objTypeTableArray = array();
 252:             $this->strExcludedTableArray = array();
 253: 
 254:             // Set the DatabaseIndex
 255:             $this->intDatabaseIndex = QCodeGen::LookupSetting($objSettingsXml, null, 'index', QType::Integer);
 256: 
 257:             // Append Suffix/Prefixes
 258:             $this->strClassPrefix = QCodeGen::LookupSetting($objSettingsXml, 'className', 'prefix');
 259:             $this->strClassSuffix = QCodeGen::LookupSetting($objSettingsXml, 'className', 'suffix');
 260:             $this->strAssociatedObjectPrefix = QCodeGen::LookupSetting($objSettingsXml, 'associatedObjectName', 'prefix');
 261:             $this->strAssociatedObjectSuffix = QCodeGen::LookupSetting($objSettingsXml, 'associatedObjectName', 'suffix');
 262: 
 263:             // Table Type Identifiers
 264:             $strTypeTableSuffixList = QCodeGen::LookupSetting($objSettingsXml, 'typeTableIdentifier', 'suffix');
 265:             $strTypeTableSuffixArray = explode(',', $strTypeTableSuffixList);
 266:             foreach ($strTypeTableSuffixArray as $strTypeTableSuffix) {
 267:                 $this->strTypeTableSuffixArray[] = trim($strTypeTableSuffix);
 268:                 $this->intTypeTableSuffixLengthArray[] = strlen(trim($strTypeTableSuffix));
 269:             }
 270:             $this->strAssociationTableSuffix = QCodeGen::LookupSetting($objSettingsXml, 'associationTableIdentifier', 'suffix');
 271:             $this->intAssociationTableSuffixLength = strlen($this->strAssociationTableSuffix);
 272: 
 273:             // Stripping TablePrefixes
 274:             $this->strStripTablePrefix = QCodeGen::LookupSetting($objSettingsXml, 'stripFromTableName', 'prefix');
 275:             $this->intStripTablePrefixLength = strlen($this->strStripTablePrefix);
 276: 
 277:             // Exclude/Include Tables
 278:             $this->strExcludePattern = QCodeGen::LookupSetting($objSettingsXml, 'excludeTables', 'pattern');
 279:             $strExcludeList = QCodeGen::LookupSetting($objSettingsXml, 'excludeTables', 'list');
 280:             $this->strExcludeListArray = explode(',',$strExcludeList);
 281:             array_walk($this->strExcludeListArray, 'array_trim');
 282: 
 283:             // Include Patterns
 284:             $this->strIncludePattern = QCodeGen::LookupSetting($objSettingsXml, 'includeTables', 'pattern');
 285:             $strIncludeList = QCodeGen::LookupSetting($objSettingsXml, 'includeTables', 'list');
 286:             $this->strIncludeListArray = explode(',',$strIncludeList);
 287:             array_walk($this->strIncludeListArray, 'array_trim');
 288: 
 289:             // ManualQuery Support
 290:             $this->blnManualQuerySupport = QCodeGen::LookupSetting($objSettingsXml, 'manualQuery', 'support', QType::Boolean);
 291: 
 292:             // Relationship Scripts
 293:             $this->strRelationships = QCodeGen::LookupSetting($objSettingsXml, 'relationships');
 294:             $this->strRelationshipsScriptPath = QCodeGen::LookupSetting($objSettingsXml, 'relationshipsScript', 'filepath');
 295:             $this->strRelationshipsScriptFormat = QCodeGen::LookupSetting($objSettingsXml, 'relationshipsScript', 'format');
 296: 
 297:             // Column Comment for ModelConnectorLabel setting.
 298:             $this->strCommentConnectorLabelDelimiter = QCodeGen::LookupSetting($objSettingsXml, 'columnCommentForModelConnector', 'delimiter');
 299: 
 300:             // Check to make sure things that are required are there
 301:             if (!$this->intDatabaseIndex)
 302:                 $this->strErrors .= "CodeGen Settings XML Fatal Error: databaseIndex was invalid or not set\r\n";
 303: 
 304:             // Aggregate RelationshipLinesQcubed and RelationshipLinesSql arrays
 305:             if ($this->strRelationships) {
 306:                 $strLines = explode("\n", strtolower($this->strRelationships));
 307:                 if ($strLines) foreach ($strLines as $strLine) {
 308:                     $strLine = trim($strLine);
 309: 
 310:                     if (($strLine) &&
 311:                         (strlen($strLine) > 2) &&
 312:                         (substr($strLine, 0, 2) != '//') &&
 313:                         (substr($strLine, 0, 2) != '--') &&
 314:                         (substr($strLine, 0, 1) != '#')) {
 315:                         $this->strRelationshipLinesQcubed[$strLine] = $strLine;
 316:                     }
 317:                 }
 318:             }
 319: 
 320:             if ($this->strRelationshipsScriptPath) {
 321:                 if (!file_exists($this->strRelationshipsScriptPath))
 322:                     $this->strErrors .= sprintf("CodeGen Settings XML Fatal Error: relationshipsScript filepath \"%s\" does not exist\r\n", $this->strRelationshipsScriptPath);
 323:                 else {
 324:                     $strScript = strtolower(trim(file_get_contents($this->strRelationshipsScriptPath)));
 325:                     switch (strtolower($this->strRelationshipsScriptFormat)) {
 326:                         case 'qcubed':
 327:                             $strLines = explode("\n", $strScript);
 328:                             if ($strLines) foreach ($strLines as $strLine) {
 329:                                 $strLine = trim($strLine);
 330: 
 331:                                 if (($strLine) &&
 332:                                     (strlen($strLine) > 2) &&
 333:                                     (substr($strLine, 0, 2) != '//') &&
 334:                                     (substr($strLine, 0, 2) != '--') &&
 335:                                     (substr($strLine, 0, 1) != '#')) {
 336:                                     $this->strRelationshipLinesQcubed[$strLine] = $strLine;
 337:                                 }
 338:                             }
 339:                             break;
 340: 
 341:                         case 'sql':
 342:                             // Separate all commands in the script (separated by ";")
 343:                             $strCommands = explode(';', $strScript);
 344:                             if ($strCommands) foreach ($strCommands as $strCommand) {
 345:                                 $strCommand = trim($strCommand);
 346: 
 347:                                 if ($strCommand) {
 348:                                     // Take out all comment lines in the script
 349:                                     $strLines = explode("\n", $strCommand);
 350:                                     $strCommand = '';
 351:                                     foreach ($strLines as $strLine) {
 352:                                         $strLine = trim($strLine);
 353:                                         if (($strLine) &&
 354:                                             (substr($strLine, 0, 2) != '//') &&
 355:                                             (substr($strLine, 0, 2) != '--') &&
 356:                                             (substr($strLine, 0, 1) != '#')) {
 357:                                             $strLine = str_replace('    ', ' ', $strLine);
 358:                                             $strLine = str_replace('        ', ' ', $strLine);
 359:                                             $strLine = str_replace('       ', ' ', $strLine);
 360:                                             $strLine = str_replace('      ', ' ', $strLine);
 361:                                             $strLine = str_replace('     ', ' ', $strLine);
 362:                                             $strLine = str_replace('    ', ' ', $strLine);
 363:                                             $strLine = str_replace('   ', ' ', $strLine);
 364:                                             $strLine = str_replace('  ', ' ', $strLine);
 365:                                             $strLine = str_replace('  ', ' ', $strLine);
 366:                                             $strLine = str_replace('  ', ' ', $strLine);
 367:                                             $strLine = str_replace('  ', ' ', $strLine);
 368:                                             $strLine = str_replace('  ', ' ', $strLine);
 369: 
 370:                                             $strCommand .= $strLine . ' ';
 371:                                         }
 372:                                     }
 373: 
 374:                                     $strCommand = trim($strCommand);
 375:                                     if ((strpos($strCommand, 'alter table') === 0) &&
 376:                                         (strpos($strCommand, 'foreign key') !== false))
 377:                                         $this->strRelationshipLinesSql[$strCommand] = $strCommand;
 378:                                 }
 379:                             }
 380:                             break;
 381: 
 382:                         default:
 383:                             $this->strErrors .= sprintf("CodeGen Settings XML Fatal Error: relationshipsScript format \"%s\" is invalid (must be either \"qcubed\" or \"sql\")\r\n", $this->strRelationshipsScriptFormat);
 384:                             break;
 385:                     }
 386:                 }
 387:             }
 388: 
 389:             $this->blnGenerateControlId = QCodeGen::LookupSetting($objSettingsXml, 'generateControlId', 'support', QType::Boolean);
 390:             $this->objModelConnectorOptions = new QModelConnectorOptions();
 391: 
 392:             $this->blnAutoInitialize = QCodeGen::LookupSetting($objSettingsXml, 'createOptions', 'autoInitialize', QType::Boolean);
 393:             
 394:             if ($this->strErrors)
 395:                 return;
 396: 
 397:             $this->AnalyzeDatabase();
 398:         }
 399: 
 400:         protected function AnalyzeDatabase() {
 401:             if (!QApplication::$Database) {
 402:                 $this->strErrors = 'FATAL ERROR: No databases are listed in the configuration file.';
 403:                 return;
 404:             }
 405:             
 406:             // Set aside the Database object
 407:             if (array_key_exists($this->intDatabaseIndex, QApplication::$Database))
 408:                 $this->objDb = QApplication::$Database[$this->intDatabaseIndex];
 409: 
 410:             // Ensure the DB Exists
 411:             if (!$this->objDb) {
 412:                 $this->strErrors = 'FATAL ERROR: No database configured at index ' . $this->intDatabaseIndex . '. Check your configuration file.';
 413:                 return;
 414:             }
 415: 
 416:             // Ensure DB Profiling is DISABLED on this DB
 417:             if ($this->objDb->EnableProfiling) {
 418:                 $this->strErrors = 'FATAL ERROR: Code generator cannot analyze the database at index ' . $this->intDatabaseIndex . ' while DB Profiling is enabled.';
 419:                 return;
 420:             }
 421: 
 422:             // Get the list of Tables as a string[]
 423:             $strTableArray = $this->objDb->GetTables();
 424: 
 425: 
 426:             // ITERATION 1: Simply create the Table and TypeTable Arrays
 427:             if ($strTableArray) {
 428:                 foreach ($strTableArray as $strTableName) {
 429: 
 430:                     // Do we Exclude this Table Name? (given includeTables and excludeTables)
 431:                     // First check the lists of Excludes and the Exclude Patterns
 432:                     if (in_array($strTableName, $this->strExcludeListArray) ||
 433:                         (strlen($this->strExcludePattern) > 0 && preg_match(":" . $this->strExcludePattern . ":i", $strTableName))
 434:                     ) {
 435: 
 436:                         // So we THINK we may be excluding this table
 437:                         // But check against the explicit INCLUDE list and patterns
 438:                         if (in_array($strTableName, $this->strIncludeListArray) ||
 439:                             (strlen($this->strIncludePattern) > 0 && preg_match(":" . $this->strIncludePattern . ":i", $strTableName))
 440:                         ) {
 441:                             // If we're here, we explicitly want to include this table
 442:                             // Therefore, do nothing
 443:                         } else {
 444:                             // If we're here, then we want to exclude this table
 445:                             $this->strExcludedTableArray[strtolower($strTableName)] = true;
 446: 
 447:                             // Exit this iteration of the foreach loop
 448:                             continue;
 449:                         }
 450:                     }
 451: 
 452:                     // Check to see if this table name exists anywhere else yet, and warn if it is
 453:                     foreach (QCodeGen::$CodeGenArray as $objCodeGen) {
 454:                         if ($objCodeGen instanceof QDatabaseCodeGen) {
 455:                             foreach ($objCodeGen->objTableArray as $objPossibleDuplicate)
 456:                                 if (strtolower($objPossibleDuplicate->Name) == strtolower($strTableName)) {
 457:                                     $this->strErrors .= 'Duplicate Table Name Used: ' . $strTableName . "\r\n";
 458:                                 }
 459:                         }
 460:                     }
 461: 
 462:                     // Perform different tasks based on whether it's an Association table,
 463:                     // a Type table, or just a regular table
 464:                     $blnIsTypeTable = false;
 465:                     foreach ($this->intTypeTableSuffixLengthArray as $intIndex => $intTypeTableSuffixLength) {
 466:                         if (($intTypeTableSuffixLength) &&
 467:                             (strlen($strTableName) > $intTypeTableSuffixLength) &&
 468:                             (substr($strTableName, strlen($strTableName) - $intTypeTableSuffixLength) == $this->strTypeTableSuffixArray[$intIndex])
 469:                         ) {
 470:                             // Let's mark, that we have type table
 471:                             $blnIsTypeTable = true;
 472:                             // Create a TYPE Table and add it to the array
 473:                             $objTypeTable = new QTypeTable($strTableName);
 474:                             $this->objTypeTableArray[strtolower($strTableName)] = $objTypeTable;
 475:                             // If we found type table, there is no point of iterating for other type table suffixes
 476:                             break;
 477: //                      _p("TYPE Table: $strTableName<br />", false);
 478:                         }
 479:                     }
 480:                     if (!$blnIsTypeTable) {
 481:                         // If current table wasn't type table, let's look for other table types
 482:                         if (($this->intAssociationTableSuffixLength) &&
 483:                             (strlen($strTableName) > $this->intAssociationTableSuffixLength) &&
 484:                             (substr($strTableName, strlen($strTableName) - $this->intAssociationTableSuffixLength) == $this->strAssociationTableSuffix)
 485:                         ) {
 486:                             // Add this ASSOCIATION Table Name to the array
 487:                             $this->strAssociationTableNameArray[strtolower($strTableName)] = $strTableName;
 488: //                      _p("ASSN Table: $strTableName<br />", false);
 489: 
 490:                         } else {
 491:                             // Create a Regular Table and add it to the array
 492:                             $objTable = new QSqlTable($strTableName);
 493:                             $this->objTableArray[strtolower($strTableName)] = $objTable;
 494: //                      _p("Table: $strTableName<br />", false);
 495:                         }
 496:                     }
 497:                 }
 498:             }
 499: 
 500: 
 501:             // Analyze All the Type Tables
 502:             if ($this->objTypeTableArray) foreach ($this->objTypeTableArray as $objTypeTable)
 503:                 $this->AnalyzeTypeTable($objTypeTable);
 504: 
 505:             // Analyze All the Regular Tables
 506:             if ($this->objTableArray) foreach ($this->objTableArray as $objTable)
 507:                 $this->AnalyzeTable($objTable);
 508: 
 509:             // Analyze All the Association Tables
 510:             if ($this->strAssociationTableNameArray) foreach ($this->strAssociationTableNameArray as $strAssociationTableName)
 511:                 $this->AnalyzeAssociationTable($strAssociationTableName);
 512: 
 513:             // Finally, for each Relationship in all Tables, Warn on Non Single Column PK based FK:
 514:             if ($this->objTableArray) foreach ($this->objTableArray as $objTable)
 515:                 if ($objTable->ColumnArray) foreach ($objTable->ColumnArray as $objColumn)
 516:                     if ($objColumn->Reference && !$objColumn->Reference->IsType) {
 517:                         $objReference = $objColumn->Reference;
 518: //                      $objReferencedTable = $this->objTableArray[strtolower($objReference->Table)];
 519:                         $objReferencedTable = $this->GetTable($objReference->Table);
 520:                         $objReferencedColumn = $objReferencedTable->ColumnArray[strtolower($objReference->Column)];
 521: 
 522: 
 523:                         if (!$objReferencedColumn->PrimaryKey) {
 524:                             $this->strErrors .= sprintf("Warning: Invalid Relationship created in %s class (for foreign key \"%s\") -- column \"%s\" is not the single-column primary key for the referenced \"%s\" table\r\n",
 525:                                 $objReferencedTable->ClassName, $objReference->KeyName, $objReferencedColumn->Name, $objReferencedTable->Name);
 526:                         } else if (count($objReferencedTable->PrimaryKeyColumnArray) != 1) {
 527:                             $this->strErrors .= sprintf("Warning: Invalid Relationship created in %s class (for foreign key \"%s\") -- column \"%s\" is not the single-column primary key for the referenced \"%s\" table\r\n",
 528:                                 $objReferencedTable->ClassName, $objReference->KeyName, $objReferencedColumn->Name, $objReferencedTable->Name);
 529:                         }
 530:                     }
 531:         }
 532: 
 533:         protected function ListOfColumnsFromTable(QSqlTable $objTable) {
 534:             $strArray = array();
 535:             $objColumnArray = $objTable->ColumnArray;
 536:             if ($objColumnArray) foreach ($objColumnArray as $objColumn)
 537:                 array_push($strArray, $objColumn->Name);
 538:             return implode(', ', $strArray);
 539:         }
 540: 
 541:         protected function GetColumnArray(QSqlTable $objTable, $strColumnNameArray) {
 542:             $objToReturn = array();
 543: 
 544:             if ($strColumnNameArray) foreach ($strColumnNameArray as $strColumnName) {
 545:                 array_push($objToReturn, $objTable->ColumnArray[strtolower($strColumnName)]);
 546:             }
 547: 
 548:             return $objToReturn;
 549:         }
 550: 
 551:         public function GenerateTable(QSqlTable $objTable) {
 552:             // Create Argument Array
 553:             $mixArgumentArray = array('objTable' => $objTable);
 554:             return $this->GenerateFiles('db_orm', $mixArgumentArray);
 555:         }
 556: 
 557:         public function GenerateTypeTable(QTypeTable $objTypeTable) {
 558:             // Create Argument Array
 559:             $mixArgumentArray = array('objTypeTable' => $objTypeTable);
 560:             return $this->GenerateFiles('db_type', $mixArgumentArray);
 561:         }
 562: 
 563:         protected function AnalyzeAssociationTable($strTableName) {
 564:             $objFieldArray = $this->objDb->GetFieldsForTable($strTableName);
 565: 
 566:             // Association tables must have 2 fields
 567:             if (count($objFieldArray) != 2) {
 568:                 $this->strErrors .= sprintf("AssociationTable %s does not have exactly 2 columns.\n",
 569:                     $strTableName);
 570:                 return;
 571:             }
 572: 
 573:             if ((!$objFieldArray[0]->NotNull) ||
 574:                 (!$objFieldArray[1]->NotNull)) {
 575:                 $this->strErrors .= sprintf("AssociationTable %s's two columns must both be not null",
 576:                     $strTableName);
 577:                 return;
 578:             }
 579: 
 580:             if (((!$objFieldArray[0]->PrimaryKey) &&
 581:                  ($objFieldArray[1]->PrimaryKey)) ||
 582:                 (($objFieldArray[0]->PrimaryKey) &&
 583:                  (!$objFieldArray[1]->PrimaryKey))) {
 584:                 $this->strErrors .= sprintf("AssociationTable %s only support two-column composite Primary Keys.\n",
 585:                     $strTableName);
 586:                 return;
 587:             }
 588: 
 589:             $objForeignKeyArray = $this->objDb->GetForeignKeysForTable($strTableName);
 590: 
 591:             // Add to it, the list of Foreign Keys from any Relationships Script
 592:             $objForeignKeyArray = $this->GetForeignKeysFromRelationshipsScript($strTableName, $objForeignKeyArray);
 593: 
 594:             if (count($objForeignKeyArray) != 2) {
 595:                 $this->strErrors .= sprintf("AssociationTable %s does not have exactly 2 foreign keys.  Code Gen analysis found %s.\n",
 596:                     $strTableName, count($objForeignKeyArray));
 597:                 return;
 598:             }
 599: 
 600:             // Setup two new ManyToManyReference objects
 601:             $objManyToManyReferenceArray[0] = new QManyToManyReference();
 602:             $objManyToManyReferenceArray[1] = new QManyToManyReference();
 603: 
 604:             // Ensure that the linked tables are both not excluded
 605:             if (array_key_exists($objForeignKeyArray[0]->ReferenceTableName, $this->strExcludedTableArray) ||
 606:                 array_key_exists($objForeignKeyArray[1]->ReferenceTableName, $this->strExcludedTableArray))
 607:                 return;
 608: 
 609:             // Setup GraphPrefixArray (if applicable)
 610:             if ($objForeignKeyArray[0]->ReferenceTableName == $objForeignKeyArray[1]->ReferenceTableName) {
 611:                 // We are analyzing a graph association
 612:                 $strGraphPrefixArray = $this->CalculateGraphPrefixArray($objForeignKeyArray);
 613:             } else {
 614:                 $strGraphPrefixArray = array('', '');
 615:             }
 616: 
 617:             // Go through each FK and setup each ManyToManyReference object
 618:             for ($intIndex = 0; $intIndex < 2; $intIndex++) {
 619:                 $objManyToManyReference = $objManyToManyReferenceArray[$intIndex];
 620: 
 621:                 $objForeignKey = $objForeignKeyArray[$intIndex];
 622:                 $objOppositeForeignKey = $objForeignKeyArray[($intIndex == 0) ? 1 : 0];
 623: 
 624:                 // Make sure the FK is a single-column FK
 625:                 if (count($objForeignKey->ColumnNameArray) != 1) {
 626:                     $this->strErrors .= sprintf("AssoiationTable %s has multi-column foreign keys.\n",
 627:                         $strTableName);
 628:                     return;
 629:                 }
 630: 
 631:                 $objManyToManyReference->KeyName = $objForeignKey->KeyName;
 632:                 $objManyToManyReference->Table = $strTableName;
 633:                 $objManyToManyReference->Column = $objForeignKey->ColumnNameArray[0];
 634:                 $objManyToManyReference->PropertyName = $this->ModelColumnPropertyName($objManyToManyReference->Column);
 635:                 $objManyToManyReference->OppositeColumn = $objOppositeForeignKey->ColumnNameArray[0];
 636:                 $objManyToManyReference->AssociatedTable = $objOppositeForeignKey->ReferenceTableName;
 637: 
 638:                 // Calculate OppositeColumnVariableName
 639:                 // Do this by first making a fake column which is the PK column of the AssociatedTable,
 640:                 // but who's column name is ManyToManyReference->Column
 641: //              $objOppositeColumn = clone($this->objTableArray[strtolower($objManyToManyReference->AssociatedTable)]->PrimaryKeyColumnArray[0]);
 642: 
 643:                 $objTable = $this->GetTable($objManyToManyReference->AssociatedTable);
 644:                 $objOppositeColumn = clone($objTable->PrimaryKeyColumnArray[0]);
 645:                 $objOppositeColumn->Name = $objManyToManyReference->OppositeColumn;
 646:                 $objManyToManyReference->OppositeVariableName = $this->ModelColumnVariableName($objOppositeColumn);
 647:                 $objManyToManyReference->OppositePropertyName = $this->ModelColumnPropertyName($objOppositeColumn->Name);
 648:                 $objManyToManyReference->OppositeVariableType = $objOppositeColumn->VariableType;
 649:                 $objManyToManyReference->OppositeDbType = $objOppositeColumn->DbType;
 650: 
 651:                 $objManyToManyReference->VariableName = $this->ModelReverseReferenceVariableName($objOppositeForeignKey->ReferenceTableName);
 652:                 $objManyToManyReference->VariableType = $this->ModelReverseReferenceVariableType($objOppositeForeignKey->ReferenceTableName);
 653: 
 654:                 $objManyToManyReference->ObjectDescription = $strGraphPrefixArray[$intIndex] . $this->CalculateObjectDescriptionForAssociation($strTableName, $objForeignKey->ReferenceTableName, $objOppositeForeignKey->ReferenceTableName, false);
 655:                 $objManyToManyReference->ObjectDescriptionPlural = $strGraphPrefixArray[$intIndex] . $this->CalculateObjectDescriptionForAssociation($strTableName, $objForeignKey->ReferenceTableName, $objOppositeForeignKey->ReferenceTableName, true);
 656: 
 657:                 $objManyToManyReference->OppositeObjectDescription = $strGraphPrefixArray[($intIndex == 0) ? 1 : 0] . $this->CalculateObjectDescriptionForAssociation($strTableName, $objOppositeForeignKey->ReferenceTableName, $objForeignKey->ReferenceTableName, false);
 658:                 $objManyToManyReference->IsTypeAssociation = ($objTable instanceof QTypeTable);
 659:                 $objManyToManyReference->Options = $this->objModelConnectorOptions->GetOptions($this->ModelClassName($objForeignKey->ReferenceTableName), $objManyToManyReference->ObjectDescription);
 660: 
 661:             }
 662: 
 663: 
 664:             // Iterate through the list of Columns to create objColumnArray
 665:             $objColumnArray = array();
 666:             foreach ($objFieldArray as $objField) {
 667:                 if (($objField->Name != $objManyToManyReferenceArray[0]->Column) &&
 668:                     ($objField->Name != $objManyToManyReferenceArray[1]->Column)) {
 669:                     $objColumn = $this->AnalyzeTableColumn($objField, null);
 670:                     if ($objColumn) {
 671:                         $objColumnArray[strtolower($objColumn->Name)] = $objColumn;
 672:                     }
 673:                 }
 674:             }
 675:             $objManyToManyReferenceArray[0]->ColumnArray = $objColumnArray;
 676:             $objManyToManyReferenceArray[1]->ColumnArray = $objColumnArray;
 677: 
 678:             // Push the ManyToManyReference Objects to the tables
 679:             for ($intIndex = 0; $intIndex < 2; $intIndex++) {
 680:                 $objManyToManyReference = $objManyToManyReferenceArray[$intIndex];
 681:                 $strTableWithReference = $objManyToManyReferenceArray[($intIndex == 0) ? 1 : 0]->AssociatedTable;
 682: 
 683:                 $objTable = $this->GetTable($strTableWithReference);
 684:                 $objArray = $objTable->ManyToManyReferenceArray;
 685:                 array_push($objArray, $objManyToManyReference);
 686:                 $objTable->ManyToManyReferenceArray = $objArray;
 687:             }
 688: 
 689:         }
 690: 
 691:         protected function AnalyzeTypeTable(QTypeTable $objTypeTable) {
 692:             // Setup the Array of Reserved Words
 693:             $strReservedWords = explode(',', QCodeGen::PhpReservedWords);
 694:             for ($intIndex = 0; $intIndex < count($strReservedWords); $intIndex++)
 695:                 $strReservedWords[$intIndex] = strtolower(trim($strReservedWords[$intIndex]));
 696: 
 697:             // Setup the Type Table Object
 698:             $strTableName = $objTypeTable->Name;
 699:             $objTypeTable->ClassName = $this->ModelClassName($strTableName);
 700: 
 701:             // Ensure that there are only 2 fields, an integer PK field (can be named anything) and a unique varchar field
 702:             $objFieldArray = $this->objDb->GetFieldsForTable($strTableName);
 703: 
 704:             if (($objFieldArray[0]->Type != QDatabaseFieldType::Integer) ||
 705:                 (!$objFieldArray[0]->PrimaryKey)) {
 706:                 $this->strErrors .= sprintf("TypeTable %s's first column is not a PK integer.\n",
 707:                     $strTableName);
 708:                 return;
 709:             }
 710: 
 711:             if (($objFieldArray[1]->Type != QDatabaseFieldType::VarChar) ||
 712:                 (!$objFieldArray[1]->Unique)) {
 713:                 $this->strErrors .= sprintf("TypeTable %s's second column is not a unique VARCHAR.\n",
 714:                     $strTableName);
 715:                 return;
 716:             }
 717: 
 718:             // Get the rows
 719:             $objResult = $this->objDb->Query(sprintf('SELECT * FROM %s', $strTableName));
 720:             $strNameArray = array();
 721:             $strTokenArray = array();
 722:             $strExtraPropertyArray = array();
 723:             $strExtraFields = array();
 724:             $intRowWidth = count($objFieldArray);
 725:             while ($objDbRow = $objResult->GetNextRow()) {
 726:                 $strRowArray = $objDbRow->GetColumnNameArray();
 727:                 $id = $strRowArray[0];
 728:                 $name = $strRowArray[1];
 729: 
 730:                 $strNameArray[$id] = str_replace("'", "\\'", str_replace('\\', '\\\\', $name));
 731:                 $strTokenArray[$id] = $this->TypeTokenFromTypeName($name);
 732:                 if ($intRowWidth > 2) { // there are extra columns to process
 733:                     $strExtraPropertyArray[$id] = array();
 734:                     for ($i = 2; $i < $intRowWidth; $i++) {
 735:                         $strFieldName = QCodeGen::TypeColumnPropertyName($objFieldArray[$i]->Name);
 736:                         $strExtraFields[$i - 2] = $strFieldName;
 737: 
 738:                         // Get and resolve type based value
 739:                         $value = $objDbRow->GetColumn($objFieldArray[$i]->Name, $objFieldArray[$i]->Type);
 740:                         $strExtraPropertyArray[$id][$strFieldName] = $value;
 741:                     }
 742:                 }
 743: 
 744:                 foreach ($strReservedWords as $strReservedWord)
 745:                     if (trim(strtolower($strTokenArray[$id])) == $strReservedWord) {
 746:                         $this->strErrors .= sprintf("Warning: TypeTable %s contains a type name which is a reserved word: %s.  Appended _ to the beginning of it.\r\n",
 747:                             $strTableName, $strReservedWord);
 748:                         $strTokenArray[$id] = '_' . $strTokenArray[$id];
 749:                     }
 750:                 if (strlen($strTokenArray[$id]) == 0) {
 751:                     $this->strErrors .= sprintf("Warning: TypeTable %s contains an invalid type name: %s\r\n",
 752:                         $strTableName, stripslashes($strNameArray[$id]));
 753:                     return;
 754:                 }
 755:             }
 756: 
 757:             ksort($strNameArray);
 758:             ksort($strTokenArray);
 759: 
 760:             $objTypeTable->NameArray = $strNameArray;
 761:             $objTypeTable->TokenArray = $strTokenArray;
 762:             $objTypeTable->ExtraFieldNamesArray = $strExtraFields;
 763:             $objTypeTable->ExtraPropertyArray = $strExtraPropertyArray;
 764:             $objTypeTable->KeyColumn = $this->AnalyzeTableColumn ($objFieldArray[0], $objTypeTable);
 765:         }
 766: 
 767:         protected function AnalyzeTable(QSqlTable $objTable) {
 768:             // Setup the Table Object
 769:             $objTable->OwnerDbIndex = $this->intDatabaseIndex;
 770:             $strTableName = $objTable->Name;
 771:             $objTable->ClassName = $this->ModelClassName($strTableName);
 772:             $objTable->ClassNamePlural = $this->Pluralize($objTable->ClassName);
 773: 
 774:             $objTable->Options = $this->objModelConnectorOptions->GetOptions($objTable->ClassName, QModelConnectorOptions::TableOptionsFieldName);
 775: 
 776:             // Get the List of Columns
 777:             $objFieldArray = $this->objDb->GetFieldsForTable($strTableName);
 778: 
 779:             // Iterate through the list of Columns to create objColumnArray
 780:             $objColumnArray = array();
 781:             if ($objFieldArray) foreach ($objFieldArray as $objField) {
 782:                 $objColumn = $this->AnalyzeTableColumn($objField, $objTable);
 783:                 if ($objColumn) {
 784:                     $objColumnArray[strtolower($objColumn->Name)] = $objColumn;
 785:                 }
 786:             }
 787:             $objTable->ColumnArray = $objColumnArray;
 788: 
 789: 
 790: 
 791: 
 792:             // Get the List of Indexes
 793:             $objTable->IndexArray = $this->objDb->GetIndexesForTable($objTable->Name);
 794: 
 795:             // Create an Index array
 796:             $objIndexArray = array();
 797:             // Create our Index for Primary Key (if applicable)
 798:             $strPrimaryKeyArray = array();
 799:             foreach ($objColumnArray as $objColumn)
 800:                 if ($objColumn->PrimaryKey) {
 801:                     $objPkColumn = $objColumn;
 802:                     array_push($strPrimaryKeyArray, $objColumn->Name);
 803:                 }
 804:             if (count($strPrimaryKeyArray)) {
 805:                 $objIndex = new QIndex();
 806:                 $objIndex->KeyName = 'pk_' . $strTableName;
 807:                 $objIndex->PrimaryKey = true;
 808:                 $objIndex->Unique = true;
 809:                 $objIndex->ColumnNameArray = $strPrimaryKeyArray;
 810:                 array_push($objIndexArray, $objIndex);
 811: 
 812:                 if (count($strPrimaryKeyArray) == 1) {
 813:                     $objPkColumn->Unique = true;
 814:                     $objPkColumn->Indexed = true;
 815:                 }
 816:             }
 817: 
 818:             // Iterate though each Index that exists in this table, set any Columns's "Index" property
 819:             // to TRUE if they are a single-column index
 820:             if ($objTable->IndexArray) foreach ($objArray = $objTable->IndexArray as $objDatabaseIndex) {
 821:                 // Make sure the columns are defined
 822:                 if (count ($objDatabaseIndex->ColumnNameArray) == 0)
 823:                     $this->strErrors .= sprintf("Index %s in table %s indexes on no columns.\n",
 824:                         $objDatabaseIndex->KeyName, $strTableName);
 825:                 else {
 826:                     // Ensure every column exist in the DbIndex's ColumnNameArray
 827:                     $blnFailed = false;
 828:                     foreach ($objArray = $objDatabaseIndex->ColumnNameArray as $strColumnName) {
 829:                         if (array_key_exists(strtolower($strColumnName), $objTable->ColumnArray) &&
 830:                             ($objTable->ColumnArray[strtolower($strColumnName)])) {
 831:                             // It exists -- do nothing
 832:                         } else {
 833:                             // Otherwise, add a warning
 834:                             $this->strErrors .= sprintf("Index %s in table %s indexes on the column %s, which does not appear to exist.\n",
 835:                                 $objDatabaseIndex->KeyName, $strTableName, $strColumnName);
 836:                             $blnFailed = true;
 837:                         }
 838:                     }
 839: 
 840:                     if (!$blnFailed) {
 841:                         // Let's make sure if this is a single-column index, we haven't already created a single-column index for this column
 842:                         $blnAlreadyCreated = false;
 843:                         foreach ($objIndexArray as $objIndex)
 844:                             if (count($objIndex->ColumnNameArray) == count($objDatabaseIndex->ColumnNameArray))
 845:                                 if (implode(',', $objIndex->ColumnNameArray) == implode(',', $objDatabaseIndex->ColumnNameArray))
 846:                                     $blnAlreadyCreated = true;
 847: 
 848:                         if (!$blnAlreadyCreated) {
 849:                             // Create the Index Object
 850:                             $objIndex = new QIndex();
 851:                             $objIndex->KeyName = $objDatabaseIndex->KeyName;
 852:                             $objIndex->PrimaryKey = $objDatabaseIndex->PrimaryKey;
 853:                             $objIndex->Unique = $objDatabaseIndex->Unique;
 854:                             if ($objDatabaseIndex->PrimaryKey)
 855:                                 $objIndex->Unique = true;
 856:                             $objIndex->ColumnNameArray = $objDatabaseIndex->ColumnNameArray;
 857: 
 858:                             // Add the new index object to the index array
 859:                             array_push($objIndexArray, $objIndex);
 860: 
 861:                             // Lastly, if it's a single-column index, update the Column in the table to reflect this
 862:                             if (count($objDatabaseIndex->ColumnNameArray) == 1) {
 863:                                 $strColumnName = $objDatabaseIndex->ColumnNameArray[0];
 864:                                 $objColumn = $objTable->ColumnArray[strtolower($strColumnName)];
 865:                                 $objColumn->Indexed = true;
 866: 
 867:                                 if ($objIndex->Unique)
 868:                                     $objColumn->Unique = true;
 869:                             }
 870:                         }
 871:                     }
 872:                 }
 873:             }
 874: 
 875:             // Add the IndexArray to the table
 876:             $objTable->IndexArray = $objIndexArray;
 877: 
 878: 
 879: 
 880: 
 881:             // Get the List of Foreign Keys from the database
 882:             $objForeignKeys = $this->objDb->GetForeignKeysForTable($objTable->Name);
 883: 
 884:             // Add to it, the list of Foreign Keys from any Relationships Script
 885:             $objForeignKeys = $this->GetForeignKeysFromRelationshipsScript($strTableName, $objForeignKeys);
 886: 
 887:             // Iterate through each foreign key that exists in this table
 888:             if ($objForeignKeys) foreach ($objForeignKeys as $objForeignKey) {
 889: 
 890:                 // Make sure it's a single-column FK
 891:                 if (count($objForeignKey->ColumnNameArray) != 1)
 892:                     $this->strErrors .= sprintf("Foreign Key %s in table %s keys on multiple columns.  Multiple-columned FKs are not supported by the code generator.\n",
 893:                         $objForeignKey->KeyName, $strTableName);
 894:                 else {
 895:                     // Make sure the column in the FK definition actually exists in this table
 896:                     $strColumnName = $objForeignKey->ColumnNameArray[0];
 897: 
 898:                     if (array_key_exists(strtolower($strColumnName), $objTable->ColumnArray) &&
 899:                         ($objColumn = $objTable->ColumnArray[strtolower($strColumnName)])) {
 900: 
 901:                         // Now, we make sure there is a single-column index for this FK that exists
 902:                         $blnFound = false;
 903:                         if ($objIndexArray = $objTable->IndexArray) foreach ($objIndexArray as $objIndex) {
 904:                             if ((count($objIndex->ColumnNameArray) == 1) &&
 905:                                 (strtolower($objIndex->ColumnNameArray[0]) == strtolower($strColumnName)))
 906:                                 $blnFound = true;
 907:                         }
 908: 
 909:                         if (!$blnFound) {
 910:                             // Single Column Index for this FK does not exist.  Let's create a virtual one and warn
 911:                             $objIndex = new QIndex();
 912:                             $objIndex->KeyName = sprintf('virtualix_%s_%s', $objTable->Name, $objColumn->Name);
 913:                             $objIndex->Unique = $objColumn->Unique;
 914:                             $objIndex->ColumnNameArray = array($objColumn->Name);
 915: 
 916:                             $objIndexArray = $objTable->IndexArray;
 917:                             $objIndexArray[] = $objIndex;
 918:                             $objTable->IndexArray = $objIndexArray;
 919: 
 920:                             if ($objIndex->Unique)
 921:                                 $this->strWarnings .= sprintf("Notice: It is recommended that you add a single-column UNIQUE index on \"%s.%s\" for the Foreign Key %s\r\n",
 922:                                     $strTableName, $strColumnName, $objForeignKey->KeyName);
 923:                             else
 924:                                 $this->strWarnings .= sprintf("Notice: It is recommended that you add a single-column index on \"%s.%s\" for the Foreign Key %s\r\n",
 925:                                     $strTableName, $strColumnName, $objForeignKey->KeyName);
 926:                         }
 927: 
 928:                         // Make sure the table being referenced actually exists
 929:                         if ((array_key_exists(strtolower($objForeignKey->ReferenceTableName), $this->objTableArray)) ||
 930:                             (array_key_exists(strtolower($objForeignKey->ReferenceTableName), $this->objTypeTableArray))) {
 931: 
 932:                             // STEP 1: Create the New Reference
 933:                             $objReference = new QReference();
 934: 
 935:                             // Retrieve the Column object
 936:                             $objColumn = $objTable->ColumnArray[strtolower($strColumnName)];
 937: 
 938:                             // Setup Key Name
 939:                             $objReference->KeyName = $objForeignKey->KeyName;
 940: 
 941:                             $strReferencedTableName = $objForeignKey->ReferenceTableName;
 942: 
 943:                             // Setup IsType flag
 944:                             if (array_key_exists(strtolower($strReferencedTableName), $this->objTypeTableArray)) {
 945:                                 $objReference->IsType = true;
 946:                             } else {
 947:                                 $objReference->IsType = false;
 948:                             }
 949: 
 950:                             // Setup Table and Column names
 951:                             $objReference->Table = $strReferencedTableName;
 952:                             $objReference->Column = $objForeignKey->ReferenceColumnNameArray[0];
 953: 
 954:                             // Setup VariableType
 955:                             $objReference->VariableType = $this->ModelClassName($strReferencedTableName);
 956: 
 957:                             // Setup PropertyName and VariableName
 958:                             $objReference->PropertyName = $this->ModelReferencePropertyName($objColumn->Name);
 959:                             $objReference->VariableName = $this->ModelReferenceVariableName($objColumn->Name);
 960: 
 961:                             // Add this reference to the column
 962:                             $objColumn->Reference = $objReference;
 963: 
 964:                             // References will not have been correctly read earlier, so try again with the reference name
 965:                             $objColumn->Options = $this->objModelConnectorOptions->GetOptions($objTable->ClassName, $objReference->PropertyName) + $objColumn->Options;
 966: 
 967: 
 968: 
 969:                             // STEP 2: Setup the REVERSE Reference for Non Type-based References
 970:                             if (!$objReference->IsType) {
 971:                                 // Retrieve the ReferencedTable object
 972: //                              $objReferencedTable = $this->objTableArray[strtolower($objReference->Table)];
 973:                                 $objReferencedTable = $this->GetTable($objReference->Table);
 974:                                 $objReverseReference = new QReverseReference();
 975:                                 $objReverseReference->Reference = $objReference;
 976:                                 $objReverseReference->KeyName = $objReference->KeyName;
 977:                                 $objReverseReference->Table = $strTableName;
 978:                                 $objReverseReference->Column = $strColumnName;
 979:                                 $objReverseReference->NotNull = $objColumn->NotNull;
 980:                                 $objReverseReference->Unique = $objColumn->Unique;
 981:                                 $objReverseReference->PropertyName = $this->ModelColumnPropertyName($strColumnName);
 982: 
 983:                                 $objReverseReference->ObjectDescription = $this->CalculateObjectDescription($strTableName, $strColumnName, $strReferencedTableName, false);
 984:                                 $objReverseReference->ObjectDescriptionPlural = $this->CalculateObjectDescription($strTableName, $strColumnName, $strReferencedTableName, true);
 985:                                 $objReverseReference->VariableName = $this->ModelReverseReferenceVariableName($objTable->Name);
 986:                                 $objReverseReference->VariableType = $this->ModelReverseReferenceVariableType($objTable->Name);
 987: 
 988:                                 // For Special Case ReverseReferences, calculate Associated MemberVariableName and PropertyName...
 989: 
 990:                                 // See if ReverseReference is due to an ORM-based Class Inheritence Chain
 991:                                 if ((count($objTable->PrimaryKeyColumnArray) == 1) && ($objColumn->PrimaryKey)) {
 992:                                     $objReverseReference->ObjectMemberVariable = QConvertNotation::PrefixFromType(QType::Object) . $objReverseReference->VariableType;
 993:                                     $objReverseReference->ObjectPropertyName = $objReverseReference->VariableType;
 994:                                     $objReverseReference->ObjectDescription = $objReverseReference->VariableType;
 995:                                     $objReverseReference->ObjectDescriptionPlural = $this->Pluralize($objReverseReference->VariableType);
 996: 
 997:                                 // Otherwise, see if it's just plain ol' unique
 998:                                 } else if ($objColumn->Unique) {
 999:                                     $objReverseReference->ObjectMemberVariable = $this->CalculateObjectMemberVariable($strTableName, $strColumnName, $strReferencedTableName);
1000:                                     $objReverseReference->ObjectPropertyName = $this->CalculateObjectPropertyName($strTableName, $strColumnName, $strReferencedTableName);
1001:                                     // get override options for codegen
1002:                                     $objReverseReference->Options = $this->objModelConnectorOptions->GetOptions($objReference->VariableType, $objReverseReference->ObjectDescription);
1003:                                 }
1004: 
1005:                                 $objReference->ReverseReference = $objReverseReference;  // Let forward reference also see things from the other side looking back
1006: 
1007:                                 // Add this ReverseReference to the referenced table's ReverseReferenceArray
1008:                                 $objArray = $objReferencedTable->ReverseReferenceArray;
1009:                                 array_push($objArray, $objReverseReference);
1010:                                 $objReferencedTable->ReverseReferenceArray = $objArray;
1011:                             }
1012:                         } else {
1013:                             $this->strErrors .= sprintf("Foreign Key %s in table %s references a table %s that does not appear to exist.\n",
1014:                                 $objForeignKey->KeyName, $strTableName, $objForeignKey->ReferenceTableName);
1015:                         }
1016:                     } else {
1017:                         $this->strErrors .= sprintf("Foreign Key %s in table %s indexes on a column that does not appear to exist.\n",
1018:                             $objForeignKey->KeyName, $strTableName);
1019:                     }
1020:                 }
1021:             }
1022: 
1023:             // Verify: Table Name is valid (alphanumeric + "_" characters only, must not start with a number)
1024:             // and NOT a PHP Reserved Word
1025:             $strMatches = array();
1026:             preg_match('/' . $this->strPatternTableName . '/', $strTableName, $strMatches);
1027:             if (count($strMatches) && ($strMatches[0] == $strTableName) && ($strTableName != '_')) {
1028:                 // Setup Reserved Words
1029:                 $strReservedWords = explode(',', QCodeGen::PhpReservedWords);
1030:                 for ($intIndex = 0; $intIndex < count($strReservedWords); $intIndex++)
1031:                     $strReservedWords[$intIndex] = strtolower(trim($strReservedWords[$intIndex]));
1032: 
1033:                 $strTableNameToTest = trim(strtolower($strTableName));
1034:                 foreach ($strReservedWords as $strReservedWord)
1035:                     if ($strTableNameToTest == $strReservedWord) {
1036:                         $this->strErrors .= sprintf("Table '%s' has a table name which is a PHP reserved word.\r\n", $strTableName);
1037:                         unset($this->objTableArray[strtolower($strTableName)]);
1038:                         return;
1039:                     }
1040:             } else {
1041:                 $this->strErrors .= sprintf("Table '%s' can only contain characters that are alphanumeric or _, and must not begin with a number.\r\n", $strTableName);
1042:                 unset($this->objTableArray[strtolower($strTableName)]);
1043:                 return;
1044:             }
1045: 
1046:             // Verify: Column Names are all valid names
1047:             $objColumnArray = $objTable->ColumnArray;
1048:             foreach ($objColumnArray as $objColumn) {
1049:                 $strColumnName = $objColumn->Name;
1050:                 $strMatches = array();
1051:                 preg_match('/' . $this->strPatternColumnName . '/', $strColumnName, $strMatches);
1052:                 if (count($strMatches) && ($strMatches[0] == $strColumnName) && ($strColumnName != '_')) {
1053:                 } else {
1054:                     $this->strErrors .= sprintf("Table '%s' has an invalid column name: '%s'\r\n", $strTableName, $strColumnName);
1055:                     unset($this->objTableArray[strtolower($strTableName)]);
1056:                     return;
1057:                 }
1058:             }
1059: 
1060:             // Verify: Table has at least one PK
1061:             $blnFoundPk = false;
1062:             $objColumnArray = $objTable->ColumnArray;
1063:             foreach ($objColumnArray as $objColumn) {
1064:                 if ($objColumn->PrimaryKey)
1065:                     $blnFoundPk = true;
1066:             }
1067:             if (!$blnFoundPk) {
1068:                 $this->strErrors .= sprintf("Table %s does not have any defined primary keys.\n", $strTableName);
1069:                 unset($this->objTableArray[strtolower($strTableName)]);
1070:                 return;
1071:             }
1072:         }
1073: 
1074:         protected function AnalyzeTableColumn(QDatabaseFieldBase $objField, $objTable) {
1075:             $objColumn = new QSqlColumn();
1076:             $objColumn->Name = $objField->Name;
1077:             $objColumn->OwnerTable = $objTable;
1078:             if (substr_count($objField->Name, "-")) {
1079:                 $tableName = $objTable ? " in table " . $objTable->Name : "";
1080:                 $this->strErrors .= "Invalid column name" . $tableName . ": " . $objField->Name . ". Dashes are not allowed.";
1081:                 return null;
1082:             }
1083: 
1084:             $objColumn->DbType = $objField->Type;
1085: 
1086:             $objColumn->VariableType = $this->VariableTypeFromDbType($objColumn->DbType);
1087:             $objColumn->VariableTypeAsConstant = QType::Constant($objColumn->VariableType);
1088: 
1089:             $objColumn->Length = $objField->MaxLength;
1090:             $objColumn->Default = $objField->Default;
1091: 
1092:             $objColumn->PrimaryKey = $objField->PrimaryKey;
1093:             $objColumn->NotNull = $objField->NotNull;
1094:             $objColumn->Identity = $objField->Identity;
1095:             $objColumn->Unique = $objField->Unique;
1096:             if (($objField->PrimaryKey) && $objTable && (count($objTable->PrimaryKeyColumnArray) == 1))
1097:                 $objColumn->Unique = true;
1098:             $objColumn->Timestamp = $objField->Timestamp;
1099: 
1100:             $objColumn->VariableName = $this->ModelColumnVariableName($objColumn);
1101:             $objColumn->PropertyName = $this->ModelColumnPropertyName($objColumn->Name);
1102: 
1103:             // separate overrides embedded in the comment
1104: 
1105:             // extract options embedded in the comment field
1106:             if (($strComment = $objField->Comment) &&
1107:                 ($pos1 = strpos ($strComment, '{')) !== false &&
1108:                 ($pos2 = strrpos ($strComment, '}', $pos1))) {
1109: 
1110:                 $strJson = substr ($strComment, $pos1, $pos2 - $pos1 + 1);
1111:                 $a = json_decode($strJson, true);
1112: 
1113:                 if ($a) {
1114:                     $objColumn->Options = $a;
1115:                     $objColumn->Comment = substr ($strComment, 0, $pos1) . substr ($strComment, $pos2 + 1); // return comment without options
1116:                     if (!empty ($a['Timestamp'])) {
1117:                         $objColumn->Timestamp = true;   // alternate way to specify that a column is a self-updating timestamp
1118:                     }
1119:                     if ($objColumn->Timestamp && !empty($a['AutoUpdate'])) {
1120:                         $objColumn->AutoUpdate = true;
1121:                     }
1122:                 } else {
1123:                     $objColumn->Comment = $strComment;
1124:                 }
1125:             }
1126: 
1127:             // merge with options found in the design editor, letting editor take precedence
1128:             $objColumn->Options = $this->objModelConnectorOptions->GetOptions($objTable->ClassName, $objColumn->PropertyName) + $objColumn->Options;
1129: 
1130:             return $objColumn;
1131:         }
1132: 
1133:         protected function StripPrefixFromTable($strTableName) {
1134:             // If applicable, strip any StripTablePrefix from the table name
1135:             if ($this->intStripTablePrefixLength &&
1136:                 (strlen($strTableName) > $this->intStripTablePrefixLength) &&
1137:                 (substr($strTableName, 0, $this->intStripTablePrefixLength - strlen($strTableName)) == $this->strStripTablePrefix))
1138:                 return substr($strTableName, $this->intStripTablePrefixLength);
1139: 
1140:             return $strTableName;
1141:         }
1142: 
1143:         protected function GetForeignKeyForQcubedRelationshipDefinition($strTableName, $strLine) {
1144:             $strTokens = explode('=>', $strLine);
1145:             if (count($strTokens) != 2) {
1146:                 $this->strErrors .= sprintf("Could not parse Relationships Script reference: %s (Incorrect Format)\r\n", $strLine);
1147:                 $this->strRelationshipLinesQcubed[$strLine] = null;
1148:                 return null;
1149:             }
1150: 
1151:             $strSourceTokens = explode('.', $strTokens[0]);
1152:             $strDestinationTokens = explode('.', $strTokens[1]);
1153: 
1154:             if ((count($strSourceTokens) != 2) ||
1155:                 (count($strDestinationTokens) != 2)) {
1156:                 $this->strErrors .= sprintf("Could not parse Relationships Script reference: %s (Incorrect Table.Column Format)\r\n", $strLine);
1157:                 $this->strRelationshipLinesQcubed[$strLine] = null;
1158:                 return null;
1159:             }
1160: 
1161:             $strColumnName = trim($strSourceTokens[1]);
1162:             $strReferenceTableName = trim($strDestinationTokens[0]);
1163:             $strReferenceColumnName = trim($strDestinationTokens[1]);
1164:             $strFkName = sprintf('virtualfk_%s_%s', $strTableName, $strColumnName);
1165: 
1166:             if (strtolower($strTableName) == trim($strSourceTokens[0])) {
1167:                 $this->strRelationshipLinesQcubed[$strLine] = null;
1168:                 return $this->GetForeignKeyHelper($strLine, $strFkName, $strTableName, $strColumnName, $strReferenceTableName, $strReferenceColumnName);
1169:             }
1170: 
1171:             return null;
1172:         }
1173: 
1174:         protected function GetForeignKeyForSqlRelationshipDefinition($strTableName, $strLine) {
1175:             $strMatches = array();
1176: 
1177:             // Start
1178:             $strPattern = '/alter[\s]+table[\s]+';
1179:             // Table Name
1180:             $strPattern .= '[\[\`\'\"]?(' . $this->strPatternTableName . ')[\]\`\'\"]?[\s]+';
1181: 
1182:             // Add Constraint
1183:             $strPattern .= '(add[\s]+)?(constraint[\s]+';
1184:             $strPattern .= '[\[\`\'\"]?(' . $this->strPatternKeyName . ')[\]\`\'\"]?[\s]+)?[\s]*';
1185:             // Foreign Key
1186:             $strPattern .= 'foreign[\s]+key[\s]*(' . $this->strPatternKeyName . ')[\s]*\(';
1187:             $strPattern .= '([^)]+)\)[\s]*';
1188:             // References
1189:             $strPattern .= 'references[\s]+';
1190:             $strPattern .= '[\[\`\'\"]?(' . $this->strPatternTableName . ')[\]\`\'\"]?[\s]*\(';
1191:             $strPattern .= '([^)]+)\)[\s]*';
1192:             // End
1193:             $strPattern .= '/';
1194: 
1195:             // Perform the RegExp
1196:             preg_match($strPattern, $strLine, $strMatches);
1197: 
1198:             if (count($strMatches) == 9) {
1199:                 $strColumnName = trim($strMatches[6]);
1200:                 $strReferenceTableName = trim($strMatches[7]);
1201:                 $strReferenceColumnName = trim($strMatches[8]);
1202:                 $strFkName = $strMatches[5];
1203:                 if (!$strFkName)
1204:                     $strFkName = sprintf('virtualfk_%s_%s', $strTableName, $strColumnName);
1205: 
1206:                 if ((strpos($strColumnName, ',') !== false) ||
1207:                     (strpos($strReferenceColumnName, ',') !== false)) {
1208:                     $this->strErrors .= sprintf("Relationships Script has a foreign key definition with multiple columns: %s (Multiple-columned FKs are not supported by the code generator)\r\n", $strLine);
1209:                     $this->strRelationshipLinesSql[$strLine] = null;
1210:                     return null;
1211:                 }
1212: 
1213:                 // Cleanup strColumnName nad strreferenceColumnName
1214:                 $strColumnName = str_replace("'", '', $strColumnName);
1215:                 $strColumnName = str_replace('"', '', $strColumnName);
1216:                 $strColumnName = str_replace('[', '', $strColumnName);
1217:                 $strColumnName = str_replace(']', '', $strColumnName);
1218:                 $strColumnName = str_replace('`', '', $strColumnName);
1219:                 $strColumnName = str_replace('  ', '', $strColumnName);
1220:                 $strColumnName = str_replace(' ', '', $strColumnName);
1221:                 $strColumnName = str_replace("\r", '', $strColumnName);
1222:                 $strColumnName = str_replace("\n", '', $strColumnName);
1223:                 $strReferenceColumnName = str_replace("'", '', $strReferenceColumnName);
1224:                 $strReferenceColumnName = str_replace('"', '', $strReferenceColumnName);
1225:                 $strReferenceColumnName = str_replace('[', '', $strReferenceColumnName);
1226:                 $strReferenceColumnName = str_replace(']', '', $strReferenceColumnName);
1227:                 $strReferenceColumnName = str_replace('`', '', $strReferenceColumnName);
1228:                 $strReferenceColumnName = str_replace(' ', '', $strReferenceColumnName);
1229:                 $strReferenceColumnName = str_replace(' ', '', $strReferenceColumnName);
1230:                 $strReferenceColumnName = str_replace("\r", '', $strReferenceColumnName);
1231:                 $strReferenceColumnName = str_replace("\n", '', $strReferenceColumnName);
1232: 
1233:                 if (strtolower($strTableName) == trim($strMatches[1])) {
1234:                     $this->strRelationshipLinesSql[$strLine] = null;
1235:                     return $this->GetForeignKeyHelper($strLine, $strFkName, $strTableName, $strColumnName, $strReferenceTableName, $strReferenceColumnName);
1236:                 }
1237: 
1238:                 return null;
1239:             } else {
1240:                 $this->strErrors .= sprintf("Could not parse Relationships Script reference: %s (Not in ANSI SQL Format)\r\n", $strLine);
1241:                 $this->strRelationshipLinesSql[$strLine] = null;
1242:                 return null;
1243:             }
1244:         }
1245: 
1246:         protected function GetForeignKeyHelper($strLine, $strFkName, $strTableName, $strColumnName, $strReferencedTable, $strReferencedColumn) {
1247:             // Make Sure Tables/Columns Exist, or display error otherwise
1248:             if (!$this->ValidateTableColumn($strTableName, $strColumnName)) {
1249:                 $this->strErrors .= sprintf("Could not parse Relationships Script reference: \"%s\" (\"%s.%s\" does not exist)\r\n",
1250:                     $strLine, $strTableName, $strColumnName);
1251:                 return null;
1252:             }
1253: 
1254:             if (!$this->ValidateTableColumn($strReferencedTable, $strReferencedColumn)) {
1255:                 $this->strErrors .= sprintf("Could not parse Relationships Script reference: \"%s\" (\"%s.%s\" does not exist)\r\n",
1256:                     $strLine, $strReferencedTable, $strReferencedColumn);
1257:                 return null;
1258:             }
1259: 
1260:             return new QDatabaseForeignKey($strFkName, array($strColumnName), $strReferencedTable, array($strReferencedColumn));
1261:         }
1262: 
1263:         /**
1264:          * This will go through the various Relationships Script lines (if applicable) as setup during
1265:          * the __constructor() through the <relationships> and <relationshipsScript> tags in the
1266:          * configuration settings.
1267:          *
1268:          * If no Relationships are defined, this method will simply exit making no changes.
1269:          *
1270:          * @param string $strTableName Name of the table to pull foreign keys for
1271:          * @param DatabaseForeignKeyBase[] Array of currently found DB FK objects which will be appended to
1272:          * @return DatabaseForeignKeyBase[] Array of DB FK objects that were parsed out
1273:          */
1274:         protected function GetForeignKeysFromRelationshipsScript($strTableName, $objForeignKeyArray) {
1275:             foreach ($this->strRelationshipLinesQcubed as $strLine) {
1276:                 if ($strLine) {
1277:                     $objForeignKey = $this->GetForeignKeyForQcubedRelationshipDefinition($strTableName, $strLine);
1278: 
1279:                     if ($objForeignKey) {
1280:                         array_push($objForeignKeyArray, $objForeignKey);
1281:                         $this->strRelationshipLinesQcubed[$strLine] = null;
1282:                     }
1283:                 }
1284:             }
1285: 
1286:             foreach ($this->strRelationshipLinesSql as $strLine) {
1287:                 if ($strLine) {
1288:                     $objForeignKey = $this->GetForeignKeyForSqlRelationshipDefinition($strTableName, $strLine);
1289: 
1290:                     if ($objForeignKey) {
1291:                         array_push($objForeignKeyArray, $objForeignKey);
1292:                         $this->strRelationshipLinesSql[$strLine] = null;
1293:                     }
1294:                 }
1295:             }
1296: 
1297:             return $objForeignKeyArray;
1298:         }
1299: 
1300:         public function GenerateControlId($objTable, $objColumn) {
1301:             $strControlId = null;
1302:             if (isset($objColumn->Options['ControlId'])) {
1303:                 $strControlId = $objColumn->Options['ControlId'];
1304:             } elseif ($this->blnGenerateControlId) {
1305:                 $strObjectName = $this->ModelVariableName($objTable->Name);
1306:                 $strClassName = $objTable->ClassName;
1307:                 $strControlVarName = $this->ModelConnectorVariableName($objColumn);
1308:                 $strLabelName = QCodeGen::ModelConnectorControlName($objColumn);
1309: 
1310:                 $strControlId = $strControlVarName . $strClassName;
1311: 
1312:             }
1313:             return $strControlId;
1314:         }
1315: 
1316: 
1317: 
1318: 
1319:         /**
1320:          * Returns a string that will cast a variable coming from the database into a php type.
1321:          * Doing this in the template saves significant amounts of time over using QType::Cast() or GetColumn.
1322:          * @param QSqlColumn $objColumn
1323:          * @return string
1324:          * @throws Exception
1325:          */
1326:         public function GetCastString (QSqlColumn $objColumn) {
1327:             switch ($objColumn->DbType) {
1328:                 case QDatabaseFieldType::Bit:
1329:                     return ('$mixVal = (bool)$mixVal;');
1330: 
1331:                 case QDatabaseFieldType::Blob:
1332:                 case QDatabaseFieldType::Char:
1333:                 case QDatabaseFieldType::VarChar:
1334:                 case QDatabaseFieldType::Json:
1335:                     return ''; // no need to cast, since its already a string or a null
1336: 
1337:                 case QDatabaseFieldType::Date:
1338:                     return ('$mixVal = new QDateTime($mixVal, null, QDateTime::DateOnlyType);');
1339: 
1340:                 case QDatabaseFieldType::DateTime:
1341:                     return ('$mixVal = new QDateTime($mixVal);');
1342: 
1343:                 case QDatabaseFieldType::Time:
1344:                     return ('$mixVal = new QDateTime($mixVal, null, QDateTime::TimeOnlyType);');
1345: 
1346:                 case QDatabaseFieldType::Float:
1347:                 case QDatabaseFieldType::Integer:
1348:                     return ('$mixVal = (' . $objColumn->VariableType . ')$mixVal;');
1349: 
1350:                 default:
1351:                     throw new Exception ('Invalid database field type');
1352:                     exit;
1353:             }
1354:         }
1355: 
1356: 
1357: 
1358:         ////////////////////
1359:         // Public Overriders
1360:         ////////////////////
1361: 
1362:         /**
1363:          * Override method to perform a property "Get"
1364:          * This will get the value of $strName
1365:          *
1366:          * @param string strName Name of the property to get
1367:          * @return mixed
1368:          */
1369:         public function __get($strName) {
1370:             switch ($strName) {
1371:                 case 'TableArray':
1372:                     return $this->objTableArray;
1373:                 case 'TypeTableArray':
1374:                     return $this->objTypeTableArray;
1375:                 case 'DatabaseIndex':
1376:                     return $this->intDatabaseIndex;
1377:                 case 'CommentConnectorLabelDelimiter':
1378:                     return $this->strCommentConnectorLabelDelimiter;
1379:                 case 'AutoInitialize':
1380:                     return $this->blnAutoInitialize;
1381:                 case 'objSettingsXml':
1382:                     throw new QCallerException('The field objSettingsXml is deprecated');
1383:                 default:
1384:                     try {
1385:                         return parent::__get($strName);
1386:                     } catch (QCallerException $objExc) {
1387:                         $objExc->IncrementOffset();
1388:                         throw $objExc;
1389:                     }
1390:             }
1391:         }
1392: 
1393:         public function __set($strName, $mixValue) {
1394:             try {
1395:                 switch($strName) {
1396:                     default:
1397:                         return parent::__set($strName, $mixValue);
1398:                 }
1399:             } catch (QCallerException $objExc) {
1400:                 $objExc->IncrementOffset();
1401:             }
1402:         }
1403:     }
1404: 
1405:     function array_trim(&$strValue) {
1406:         $strValue = trim($strValue);
1407:     }
API documentation generated by ApiGen