Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3.2 #1324

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open

V3.2 #1324

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b0a72d0
Moves special handling of flags to SetFieldType.
spekary Mar 19, 2017
11c833e
Removes the dependency in the database adapter on the query builder. …
spekary Mar 19, 2017
37971e3
Merge pull request #1218 from spekary/bugfix-BetterBinaryHandling
spekary Mar 23, 2017
c95a884
Merge pull request #1219 from spekary/bugfix-RemoveQueryBuilderDepend…
spekary Mar 23, 2017
9afb2d1
Merge remote-tracking branch 'qcubed/v3.1' into v3.2
spekary Mar 28, 2017
4c3ca55
Merge remote-tracking branch 'qcubed/v3.1' into v3.2
spekary Mar 29, 2017
6c2eba9
Adding OnClick message handler and fixing up some type checking to us…
spekary Apr 4, 2017
a4bc0dd
Adding the ability to make an application constructor
spekary Apr 4, 2017
c233276
Adds the ability to check if an object is associated by checking the …
spekary Apr 4, 2017
bf3b82e
Merge pull request #1245 from spekary/feature-OnClick
spekary Apr 4, 2017
6d5f5bf
Merge pull request #1247 from spekary/bugfix-ApplicationBaseConstructor
spekary Apr 4, 2017
ab5c1a8
Merge pull request #1248 from spekary/feaure-IsAssociatedObjectByKey
spekary Apr 4, 2017
bd27356
Fixing signature for AddAction for controls that override this.
spekary Apr 9, 2017
6f7f89e
Merge pull request #1250 from spekary/OnClick-Regression
spekary Apr 9, 2017
fe5e3a4
Moving NoScriptAjaxAction to _actions file where it belongs.
spekary Apr 22, 2017
2543707
Fixing project status in sample data.
spekary Apr 22, 2017
f87142d
Typo
spekary Apr 22, 2017
23263d6
Removing outdated code
spekary Apr 27, 2017
07b3589
Generating jqui 1.12 support
spekary May 2, 2017
4b2b1d7
Fixing reference to latest jquery ui. Removing our own build of it, s…
spekary May 2, 2017
586831c
Removing deprecated data grid html test.
spekary May 2, 2017
0868d8d
Merge pull request #1256 from spekary/bugfix-reorg
spekary May 4, 2017
891029b
Merge pull request #1260 from spekary/bugfix-jqui1-12
spekary May 4, 2017
576baf1
InsertOrUpdate now returns the autoincremented ID
May 17, 2017
8439874
Merge remote-tracking branch 'qcubed/v3.1' into v3.2
spekary May 22, 2017
902d0fb
Merge remote-tracking branch 'origin/bugfix-BlockedActionsWithDelay' …
spekary May 22, 2017
976502e
Merge pull request #1262 from matthiaz/patch-21
spekary Jul 7, 2017
b38f2a4
Profile.php should not be accessible in production. Most people remov…
May 1, 2020
b9ed267
fix typo
May 1, 2020
a102b9a
Merge pull request #1320 from qcubed/fix-security-issue-profiler
matthiaz Aug 11, 2020
bc2bee2
Merge branch 'master' into v3.2
matthiaz Aug 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16,375 changes: 0 additions & 16,375 deletions assets/js/jquery/jquery-ui.custom.js

This file was deleted.

13 changes: 0 additions & 13 deletions assets/js/jquery/jquery-ui.custom.min.js

This file was deleted.

283 changes: 283 additions & 0 deletions assets/php/_devtools/jquery_ui_gen/jq_control_gen-1.11.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
<?php

/**
* This script generates the Jq*Gen classes by scraping the JQueryUI documentation web site.
* Current version: JQueryUI 1.11
*/

require('jq_control.php');
require('qcubed.inc.php');

class HtmlJqDoc extends JqDoc {

public function description($desc_node) {
$description = '';
while ($desc_node) {
if (strpos($desc_node->plaintext, 'Code examples:') !== false) {
break;
}
// if ($description)
// $description .= "\n";
$text = $desc_node->outertext();
$text = preg_replace('/<(\w+)[^>]*>\s*/', '<$1>', $text);
$text = preg_replace('/\s*<\/(\w+)>/', '</$1>', $text);
$text = preg_replace('/<\/code>\s*<code>/', '', $text);
$text = preg_replace('/<div>/', '', $text);
$text = preg_replace('/<\/div>/', '', $text);

$text = preg_replace('/<strong>/', '', $text);
$text = preg_replace('/<\/strong>/', '', $text);

$description .= $text;
$desc_node = $desc_node->next_sibling();
}
return $description;
}

public function __construct($strUrl, $strJqClass = null, $strJqSetupFunc = null, $strQcClass = null, $strQcBaseClass = 'QPanel')
{
$this->hasDisabledProperty = false;
$html = file_get_html($strUrl);

if ($strJqClass === null) {
$nodes = $html->find('h1.entry-title');
$strJqClass = preg_replace('/ .*/', '', $nodes[0]->plaintext);
}

parent::__construct($strJqClass, $strJqSetupFunc, $strQcClass, $strQcBaseClass);

$htmlOptions = $html->find('section[id=options] div.api-item');

foreach ($htmlOptions as $htmlOption) {
$type = $this->add_option($htmlOption);
if ($this->is_event_option($type)) {
$this->add_event($htmlOption, $type);
}
}

$htmlEvents = $html->find('section[id=events] div.api-item');
foreach ($htmlEvents as $htmlEvent) {
$this->add_event($htmlEvent);
}

$htmlMethods = $html->find('section[id=methods] div.api-item');
$this->reset_names();
foreach ($htmlMethods as $htmlMethod) {
$this->add_method($htmlMethod);
}
}

public function add_option($htmlOption) {
$nodes = $htmlOption->find('h3');
$name_node = $nodes[0];
$origName = $name = preg_replace('/\W.*/', '', $name_node->innertext());

$nodes = $htmlOption->find('div.option-type');
$type = preg_replace('/Type: /', '', $nodes[0]->plaintext);
$type = trim($type);
if ($this->is_event_option($type))
return $type;

// sometimes jQuery controls (e.g. tabs) uses the same property name for more than one options
$name = $this->unique_name($name);

$defaultValue = null;
$nodes = $htmlOption->find('div.default');
if ($nodes) {
$desc_node = $nodes[0]->next_sibling();
$nodes = $nodes[0]->find('code');
$defaultValue = html_entity_decode($nodes[0]->plaintext, ENT_COMPAT, 'UTF-8');
} else {
$desc_node = $name_node->next_sibling();
}
$description = $this->description($desc_node);
if ($name == 'disabled') {
$this->hasDisabledProperty = true;
}

$this->options[] = new Option($name, $origName, $type, $defaultValue, $description);
return $type;
}

public function is_event_option($type) {
return stripos($type, 'function') !== false && strpos($type, ' or ') === false;
}

public function add_event($htmlEvent, $type = null) {
$nodes = $htmlEvent->find('h3');
$name_node = $nodes[0];
$origName = $name = preg_replace('/\W.*/', '', $name_node->innertext());
if (substr($name, 0, 2) !== "on") {
$name = "on" . ucfirst($name);
}

if ($type == null) {
$nodes = $htmlEvent->find('span.returns');
$type = preg_replace('/Type: /', '', $nodes[0]->plaintext);
}
$type = trim($type);

// sometimes jQuery controls (e.g. tabs) uses the same property name for more than one options
$name = $this->unique_name($name);

$desc_node = $name_node->next_sibling();
$description = $this->description($desc_node);

if (stripos($type, 'function') === 0) { // this can only be declared at init time
$this->options[] = new Event($this->strQcClass, $name, $origName, $type, $description);
} else {
$this->events[] = new Event($this->strQcClass, $name, $origName, $type, $description);
}
}

public function add_method($htmlMethod) {
$nodes = $htmlMethod->find('h3');
$name_node = $nodes[0];
$origName = $name = preg_replace('/\W.*/', '', $name_node->innertext());
if ($origName === "widget") {
// the widget method doesn't make much sense in our context
// skip it
return;
}

$signature = preg_replace('/\).*/', ')', $name_node->innertext());
$signature = str_replace('[,', ',[', $signature);

// sometimes jQuery controls (e.g. tabs) uses the same property name for more than one options
$name = $this->unique_name($name);

$desc_node = $name_node->next_sibling();
$description = $this->description($desc_node);

$this->methods[] = new Method($name, $origName, $signature, $description);
}
}

$aryPathsList = array();

function CamelCaseFromDash($strName) {
$strToReturn = '';

// If entire underscore string is all uppercase, force to all lowercase
// (mixed case and all lowercase can remain as is)
if ($strName == strtoupper($strName))
$strName = strtolower($strName);

while (($intPosition = strpos($strName, "-")) !== false) {
// Use 'ucfirst' to create camelcasing
$strName = ucfirst($strName);
if ($intPosition == 0) {
$strName = substr($strName, 1);
} else {
$strToReturn .= substr($strName, 0, $intPosition);
$strName = substr($strName, $intPosition + 1);
}
}

$strToReturn .= ucfirst($strName);
return $strToReturn;
}


function jq_control_gen($strUrl, $strQcClass = null, $strQcBaseClass = 'QPanel') {
global $aryPathsList;

$strOutDirControls = __QCUBED_CORE__ . "/../install/project/includes/controls";
$strOutDirControlsBase = __QCUBED_CORE__ . "/base_controls";


$jqControlGen = new JqControlGen();
$objJqDoc = new HtmlJqDoc($strUrl, null, null, $strQcClass, $strQcBaseClass);
$jqControlGen->GenerateControl($objJqDoc, $strOutDirControls, $strOutDirControlsBase);

foreach ($objJqDoc->events as $event) {
$aryPathsList[strtolower($event->eventClassName)] =
sprintf("__QCUBED_CORE__ . '/base_controls/%sGen.class.php'", $objJqDoc->strQcClass);
}
foreach ($objJqDoc->options as $option) {
if ($option instanceof Event) {
$aryPathsList[strtolower($option->eventClassName)] =
sprintf("__QCUBED_CORE__ . '/base_controls/%sGen.class.php'", $objJqDoc->strQcClass);
}
}
$aryPathsList[strtolower($objJqDoc->strQcClass) . 'gen'] =
sprintf("__QCUBED_CORE__ . '/base_controls/%sGen.class.php'", $objJqDoc->strQcClass);

$aryPathsList[strtolower($objJqDoc->strQcClass) . 'base'] =
sprintf("__QCUBED_CORE__ . '/base_controls/%sBase.class.php'", $objJqDoc->strQcClass);


$aryPathsList[strtolower($objJqDoc->strQcClass)] =
sprintf("__INCLUDES__ . '/controls/%s.class.php'", $objJqDoc->strQcClass);
}

// generate an include file for use by the ui classes
function jq_inc_gen() {
$html = file_get_html('http://jqueryui.com/themeroller/');
$nodes = $html->find('#icons', 0)->children();

$aNames = array();
foreach ($nodes as $node) {
$name = $node->title;
$aNames[] = substr($name, 9); // delete '.ui-icon-'
}

$strOutFileName = __QCUBED_CORE__ . '/base_controls/'. '_jq_ui.inc.php';
$strResult = "// Generated include file for JQuery UI related classes.\n\n// JQuery UI icon names scraped from the themeroller website.\n\n";
$strResult .= "abstract class JqIcon {\n";
foreach ($aNames as $name) {
$strVarName = CamelCaseFromDash($name);
if ($strVarName == 'Print') {
$strVarName = 'Jq' . $strVarName; // avoid reserved word
}
$strResult .= sprintf("\tconst %s = 'ui-icon-%s';\n", $strVarName, $name);
}
$strResult .= "}";
$strResult = "<?php\n" . $strResult . "\n?>";

file_put_contents($strOutFileName, $strResult);
}

$baseUrl = "http://api.jqueryui.com";

// QBlock control uses these differently to make these capabilities a part of any block control

jq_control_gen($baseUrl."/Draggable", null, 'QControl');
jq_control_gen($baseUrl."/Droppable", null, 'QControl');
jq_control_gen($baseUrl."/Resizable", null, 'QControl');

jq_control_gen($baseUrl."/Selectable");
jq_control_gen($baseUrl."/Sortable");

jq_control_gen($baseUrl."/Accordion");
jq_control_gen($baseUrl."/Autocomplete", null, 'QTextBox');
jq_control_gen($baseUrl."/Button", 'QJqButton', 'QButton');
jq_control_gen($baseUrl."/Button", 'QJqCheckBox', 'QCheckBox');
jq_control_gen($baseUrl."/Button", 'QJqRadioButton', 'QRadioButton');
jq_control_gen($baseUrl."/Datepicker");
jq_control_gen($baseUrl."/Datepicker", 'QDatepickerBox', 'QTextBox');
jq_control_gen($baseUrl."/Dialog");
jq_control_gen($baseUrl."/Progressbar");
jq_control_gen($baseUrl."/Slider");
jq_control_gen($baseUrl."/Tabs");
jq_control_gen($baseUrl."/Menu");
jq_control_gen($baseUrl."/Spinner", null, 'QTextBox');
jq_control_gen($baseUrl."/SelectMenu", 'QSelectMenu', 'QListBox');
//jq_control_gen($baseUrl."/Tooltip"); A JQuery UI tool tip is not a control, but rather is straight javascript that changes how tooltips work on a whole page. Implementation would need to be very different.

jq_inc_gen();

// additional auto-includes
$aryPathsList["qautocompletelistitem"] = "__QCUBED_CORE__ . '/base_controls/QAutocompleteBase.class.php'";
$aryPathsList["jqicon"] = "__QCUBED_CORE__ . '/base_controls/_jq_ui.inc.php'";

$strResult = '';
foreach ($aryPathsList as $class=>$path) {
$strResult .= "QApplicationBase::\$ClassFile['$class'] = $path;\n";
}

$strResult = "<?php\n" . $strResult . "\n?>";

$strOutFileName = __QCUBED_CORE__ . '/'. '_jq_paths.inc.php';

file_put_contents($strOutFileName, $strResult);
9 changes: 5 additions & 4 deletions assets/php/_devtools/jquery_ui_gen/jq_control_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/**
* This script generates the Jq*Gen classes by scraping the JQueryUI documentation web site.
* Current version: JQueryUI 1.11
* Current version: JQueryUI 1.12
*/

require('jq_control.php');
Expand Down Expand Up @@ -251,9 +251,10 @@ function jq_inc_gen() {

jq_control_gen($baseUrl."/Accordion");
jq_control_gen($baseUrl."/Autocomplete", null, 'QTextBox');
jq_control_gen($baseUrl."/Button", 'QJqButton', 'QButton');
jq_control_gen($baseUrl."/Button", 'QJqCheckBox', 'QCheckBox');
jq_control_gen($baseUrl."/Button", 'QJqRadioButton', 'QRadioButton');
jq_control_gen($baseUrl."/button", 'QJqButton', 'QButton');
jq_control_gen($baseUrl."/checkboxradio", 'QJqCheckBox', 'QCheckBox');
jq_control_gen($baseUrl."/checkboxradio", 'QJqRadioButton', 'QRadioButton');
jq_control_gen($baseUrl."/controlgroup");
jq_control_gen($baseUrl."/Datepicker");
jq_control_gen($baseUrl."/Datepicker", 'QDatepickerBox', 'QTextBox');
jq_control_gen($baseUrl."/Dialog");
Expand Down
4 changes: 2 additions & 2 deletions assets/php/examples/mysql_innodb.sql
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ ALTER TABLE `person_persontype_assn` ADD CONSTRAINT person_persontype_assn_2 FOR
#========================================================================== #

INSERT INTO project_status_type (name, description, guidelines, is_active) VALUES ('Open', 'The project is currently active', 'All projects that we are working on should be in this state', 1);
INSERT INTO project_status_type (name, description, guidelines, is_active) VALUES ('Cancelled', 'The project has been canned', null, 1);
INSERT INTO project_status_type (name, description, guidelines, is_active) VALUES ('Completed', 'The project has been completed successfully', 'Celebrate successes!', 1);
INSERT INTO project_status_type (name, description, guidelines, is_active) VALUES ('Cancelled', 'The project has been canned', null, 0);
INSERT INTO project_status_type (name, description, guidelines, is_active) VALUES ('Completed', 'The project has been completed successfully', 'Celebrate successes!', 0);

INSERT INTO person_type VALUES(1, 'Contractor');
INSERT INTO person_type VALUES(2, 'Manager');
Expand Down
31 changes: 19 additions & 12 deletions assets/php/profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,34 @@
require_once('./qcubed.inc.php');

//Exit gracefully if called directly or profiling data is missing.
if ( !isset($_POST['intDatabaseIndex']) && !isset($_POST['strProfileData']) && !isset($_POST['strReferrer']) )
exit('Nothing to profile. No Database Profiling data recived.');

if ( !isset($_POST['intDatabaseIndex']) || !isset($_POST['strProfileData']) || !isset($_POST['strReferrer']) )
if ( !isset($_POST['intDatabaseIndex']) && !isset($_POST['strProfileData']) && !isset($_POST['strReferrer']) ) {
exit('Nothing to profile. No Database Profiling data received.');
}
if ( !isset($_POST['intDatabaseIndex']) || !isset($_POST['strProfileData']) || !isset($_POST['strReferrer']) ) {
throw new Exception('Database Profiling data appears to have been corrupted.');

}

$intDatabaseIndex = intval($_POST['intDatabaseIndex']);
$objDb = QApplication::$Database[$intDatabaseIndex];

if (! $objDb->EnableProfiling ) {
throw new Exception('Database Profiling has not been turned on. You can turn it on by setting "profiling" to true (but never do this in production since this opens up security holes).');

}

$strReferrer = QApplication::HtmlEntities($_POST['strReferrer']);

$objProfileArray = unserialize(base64_decode($_POST['strProfileData']));
$objProfileArray = QType::Cast($objProfileArray, QType::ArrayType);
$intCount = count($objProfileArray);

function PrintExplainStatement($strOriginalQuery) {
global $intDatabaseIndex;
function PrintExplainStatement($objDb, $strOriginalQuery) {
if (substr_count($strOriginalQuery, "AUTOCOMMIT=1") > 0) {
return null;
}
$result = "";

$objDb = QApplication::$Database[$intDatabaseIndex];

$objDbResult = $objDb->ExplainStatement($strOriginalQuery);
if (!$objDbResult) {
return "";
Expand Down Expand Up @@ -141,9 +148,9 @@ function HideAll() {
</div>
<div id="hright">
<b>Database Index:</b> <?php _p($intDatabaseIndex); ?>&nbsp;&nbsp;
<b>Database Type:</b> <?php _p(QApplication::$Database[$intDatabaseIndex]->Adapter); ?><br/>
<b>Database Server:</b> <?php _p(QApplication::$Database[$intDatabaseIndex]->Server); ?>&nbsp;&nbsp;
<b>Database Name:</b> <?php _p(QApplication::$Database[$intDatabaseIndex]->Database); ?><br/>
<b>Database Type:</b> <?php _p($objDb->Adapter); ?><br/>
<b>Database Server:</b> <?php _p($objDb->Server); ?>&nbsp;&nbsp;
<b>Database Name:</b> <?php _p($objDb->Database); ?><br/>
<b>Profile Generated From:</b> <?php _p($strReferrer, false); ?>
</div>
<div class="clear"></div>
Expand Down Expand Up @@ -197,7 +204,7 @@ function HideAll() {
echo'<div class="time">';
printf("Query took %.1f ms", $dblTimeInfo * 1000);
?>
<?php $explainStatement = PrintExplainStatement($strQuery); ?>
<?php $explainStatement = PrintExplainStatement($objDb, $strQuery); ?>
<a href="#" onClick="return Toggle('query<?php _p($intIndex); ?>')" id="buttonquery<?php _p($intIndex); ?>" class="queryButton smallbutton">
Show SQL
</a>
Expand Down