Skip to content
Browse files

-Added the other unit tests to the repo

-Minor refactoring
  • Loading branch information...
1 parent 6976c87 commit 93f4c20765b4857c516dab2babbd8c474b823adb @anfurny committed Jan 25, 2012
View
BIN ALfields logo.png
Deleted file not rendered
View
BIN ALfields logo.xcf
Binary file not shown.
View
BIN ALfields logo_small.xcf
Binary file not shown.
View
18 AliveFields/AcField/AcField.php
@@ -14,13 +14,12 @@
*
*
*
- * @todo move unnecessary files out of root directory.
- * @todo drastically refactor ajax_field, ajax_list, ajax_field_multiple
+ * @todo drastically refactor ajax_field_multiple
*
* @todo deal with: 'Definitions to explain the following fields:'
* @todo consolidate error reporting, turn off deprecated on release mode. (alexrohde.com server)
* @todo make unit tests for multi fields.
- * @todo refactor ajax_field (it should be two separate methods for save and load). Check the other controllers too.
+ * @todo refactor Check the other controllers too.
* @todo move to mysqli
* @todo Make sure validations work of both types on the new whatcha-ma-call-it list
* @todo to do: make new superior error handler thingies.
@@ -281,17 +280,6 @@ function do_validations(& $prev_value, $key_val) {
return true;
}
- /**
- *
- */
- function differentiate_options($field, $table, $pkey) {
- throw Exception("Not implemented");
- // Notes to self:
- //set the session variable to load options for these fields.
- //?? Set the session variable to load/save previous field, not load options from them.
- //since no columns are used in javascript, javascript doesn't have to be updated?
- // but I do want savable and loadable to apply. Those make no sense before differentiate_options
- }
/**
* Include the relevant javascript files necessary to power the view.
@@ -560,7 +548,7 @@ function register_validator($callback) {
function request_handler($request) {
if (($request['AcFieldRequest'] == 'loadfield') || ($request['AcFieldRequest'] == 'savefield')) {
require_once (__DIR__ . "/../_internalInclude/ajax_field.php");
- return acField_Controller($this, $request);
+ return acField_Controller($this, $request);
} else {
return throw_error("Nonexistant Request");
}
View
322 AliveFields/_internalInclude/ajax_field.php
@@ -3,176 +3,242 @@
/**
* The normal save and load operations have been moved out to this file
* to enhance readability of AcField
- *
+ *
* @param AcField $fake_this The context of the handling AcField
* @param string $request Whether to load or save
- * @return associative_array Response information
+ * @return associative_array Response information
*/
-
function acField_Controller(& $fake_this, $request) {
/* Load the request information into more-readable variables.
*/
$requestingPage = $request['requesting_page'];
- $fieldUniqueId = $request['request_field'];
+ $fieldUniqueId = $request['request_field'];
+ $this_field = AcField::instance_from_id($fieldUniqueId);
+ $table = $this_field->bound_table;
+ $this_field_session = & $_SESSION['_AcField'][$requestingPage][$fieldUniqueId];
+
+ if (empty($this_field_session)) {
+ throw_error(AcField::ERROR_INVALID_TOKEN);
+ }
+ $this_field = AcField::instance_from_id($fieldUniqueId);
+ $table = $this_field->bound_table;
+ $join_clause = '';
+
+ if ($request['action'] === 'save') {
+ return save_action($fake_this, $request);
+ } elseif (($request['action'] === 'hardcoded_load') || ($request['action'] === 'dynamic_load')) {
+ $tmp = load_action($fake_this, $request);
+ return $tmp;
+ /* elseif (($dataRequest['action'] === "insert"))
+ {
+ return insert_action();
+ } */
+ } else {
+ trigger_error("Unknow Action:" . $request['action'], E_USER_ERROR);
+ }
+}
+
+function save_action(& $fake_this, $request) {
+
+ $requestingPage = $request['requesting_page'];
+ $fieldUniqueId = $request['request_field'];
$this_field_session = & $_SESSION['_AcField'][$requestingPage][$fieldUniqueId];
-
- if (empty($this_field_session))
- throw_error(AcField::ERROR_INVALID_TOKEN);
+// reconstruct theAcField based on the Id (no need to pass the whole field through session)
$this_field = AcField::instance_from_id($fieldUniqueId);
$table = $this_field->bound_table;
- $join_clause = '';
- if (($request['action'] === 'save')) {
- // reconstruct theAcField based on the Id (no need to pass the whole field through session)
- $theAcField = AcField::instance_from_id($fieldUniqueId);
- $values = $request['fieldInfo'];
+ ////////////////////////////////////////////////////////////////////////////////
+ // Validity Checks
- //Check Permissions
- if ($this_field->savable != AcField::SAVE_YES)
- throw_error(AcField::ERROR_SAVE_DISALLOWED);
+ if ($this_field->savable != AcField::SAVE_YES)
+ throw_error(AcField::ERROR_SAVE_DISALLOWED);
- foreach ($values as $x) {
- //so even though we are looping right here, as written controls can only update 1 field per ajax request. This loop is more for theoretical future use then?
- $values_clause[] = $fake_this->adapter->escape_field_name($this_field->bound_field) . " = " . $fake_this->adapter->escape_field_value($x[1]) . " ";
- }
- $values_clause = implode(' , ', $values_clause);
- // WHY ARE WE USING $x[1] OUTSIDE OF THE LOOP that defines $X[1]?
- if ($fake_this instanceof AcList)
- verify_control_could_contain_value($fake_this, $requestingPage, $fieldUniqueId, ($x[1]), 'optionValue') or throw_error('expectedError');
+ //library isn't currently designed to securely handle a save before a load.
+ if (!isset($this_field_session['loaded_where_clause'])) {
+ throw_error('Not Supported');
}
- /* elseif (($dataRequest['action'] === "insert")) // I haven't yet ported this to the new format for this library and thus it is non-functional
- {
- foreach ($values as $x)
- {
- $values_clause1[] = cleanFieldName($x[0]);
- $values_clause2[] = cleanFieldValue($x[1]);
- $values_clause = " (" . join(",", $values_clause1) . ") VALUES (" . join(",", $values_clause2) . ") " ;
- if (isset($where_clause))
- trigger_error("Cannot use limiting conditions in an insert", E_USER_ERROR );
+ // Validity Checks
+ ///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+ // Set the values clause
+
+ /**
+ * Values is a multidimensional array of the form:
+ * array
+ * array [ UNUSED , 'new value' ]
+ *
+ * The only case the outer array will have more than 1 element is if insert
+ * is ever implemented in this library.
+ */
+ $all_values = $request['fieldInfo'];
+ if (count($all_values) != 1)
+ throw_error("Invalid Save Request");
+ $value = $all_values[0][1];
+
+ $values_clause = $fake_this->adapter->escape_field_name($this_field->bound_field)
+ . " = " . $fake_this->adapter->escape_field_value($value) . " ";
+
+ /**
+ * Ensure that every value we're saving is plausible. This only applies to
+ * lists where differentiate options has been used and each field represents
+ * on of a set bunch of options from a join table.
+ */
+ if ($fake_this instanceof AcList) {
- if (strpos($SECURITY_PERMISSIONS["normal"][$table], "W") === false)
- trigger_error("Insufficient Permissions to write to table -$table-", E_USER_ERROR );
- }
- } */
- elseif (($request['action'] === 'hardcoded_load') || ($request['action'] === 'dynamic_load')) {
- $sourceUniqueId = $request['source_field'];
+ $res = verify_control_could_contain_value($fake_this, $requestingPage, $fieldUniqueId, ($value), 'optionValue');
+ if (! $res)
+ {
+ throw_error('expectedError');
+ }
+ }
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * For security we apply all the limiting filters that restrict what
+ * values can be *loaded* into a control to the process of SAVING a control.
+ *
+ * This is thus stored in the session.
+ */
+ $sql = "SELECT COUNT(*) as count_rec from $table " . $this_field_session['loaded_join_clause']
+ . " WHERE " . join($this_field_session['loaded_where_clause'], " AND ");
+
+ $security_check = $fake_this->adapter->query_read($sql);
+ if (!$security_check[0]['count_rec']) {
+ throw_error('Security issue');
+ } else if ($security_check[0]['count_rec'] > 1) {
+// You probably don't want to do something that affects multiple rows since you are usually operating on primary key.
+//However if you know what you are doing, you can disable this restriction by commenting the following line
+ throw_error('Cancelled. Affects multiple rows.');
+ }
- if (!$this_field->loadable)
- throw_error(AcField::ERROR_LOAD_DISALLOWED); //security violation
+ /**
+ * Apply save validations
+ */
+ foreach ($all_values as $x)
+ if (!$this_field->do_validations($x[1], $this_field_session['loaded_pkey']))
+ throw_error('Could not save field: Validation Failed');
- $values_clause = $this_field->bound_field . ' as answer ';
+ /**
+ * Perform the actual save
+ */
+ $sql = "UPDATE $table SET $values_clause WHERE " . join($this_field_session['loaded_where_clause'], " AND ");
+ $fake_this->adapter->query_write($sql, 1);
+ $result['value'] = "success";
+ return $result;
+}
- if ($request['action'] === 'dynamic_load') {
- $where_clause['key_piece'] = $fake_this->adapter->escape_table_name($this_field->bound_table)
- . "." . $fake_this->adapter->escape_field_name($this_field->bound_pkey) . " = "
- . $fake_this->adapter->escape_field_value($request['primaryInfo'][1]);
+function load_action(& $fake_this, $request) {
+ $requestingPage = $request['requesting_page'];
+ $fieldUniqueId = $request['request_field'];
+ $this_field_session = & $_SESSION['_AcField'][$requestingPage][$fieldUniqueId];
+ $this_field_session['loaded_join_clause'] = '';
+ /**
+ * SourceUniqueID is the AcField's unique ID of the field that *allegedly*
+ * told this control to load (i.e. the client claims this field is a dependent
+ * field of SourceUniqueID)
+ */
+ $sourceUniqueId = $request['source_field'];
+ $this_field = AcField::instance_from_id($fieldUniqueId);
+ $table = $this_field->bound_table;
+ $join_clause = '';
+ if (!$this_field->loadable)
+ throw_error(AcField::ERROR_LOAD_DISALLOWED); //security violation
- if (isset($_SESSION['_AcField'][$requestingPage][$sourceUniqueId]['filters']))
- if (count($_SESSION['_AcField'][$requestingPage][$sourceUniqueId]['filters'])) {
- $source_field = $_SESSION['_AcField'][$requestingPage][$sourceUniqueId];
+ $values_clause = $this_field->bound_field . ' as answer ';
- //verify that this control is indeed allowed to update the other control. Do this verification by looking at session records.
- if (!in_array($this_field_session["unique_id"], $source_field['dependent_fields']))
- throw_error(AcField::ERROR_LOAD_DISALLOWED); //This indicates attempted hacking.
+ if ($request['action'] === 'dynamic_load') {
+ $where_clause['key_piece'] = $fake_this->adapter->escape_table_name($this_field->bound_table)
+ . "." . $fake_this->adapter->escape_field_name($this_field->bound_pkey) . " = "
+ . $fake_this->adapter->escape_field_value($request['primaryInfo'][1]);
- $join_clause[] = $source_field['bound_table'] . ' ON ' .
- $fake_this->adapter->escape_table_name($this_field->bound_table)
- . "." . $fake_this->adapter->escape_field_name($this_field->bound_pkey)
- . " = " . $fake_this->adapter->escape_table_name($source_field['bound_table'])
- . "." . $fake_this->adapter->escape_field_value($source_field["bound_pkey"]);
- //All join clauses need to have INNER JOINs between them
- if (count($join_clause) > 0)
- $join_clause = 'INNER JOIN ' . join($join_clause, ' INNER JOIN ');
+ if (isset($_SESSION['_AcField'][$requestingPage][$sourceUniqueId]['filters'])) {
+ if (count($_SESSION['_AcField'][$requestingPage][$sourceUniqueId]['filters'])) {
+
+ // Source_field = Field that told *this* to load
+ $source_field = $_SESSION['_AcField'][$requestingPage][$sourceUniqueId];
- $this_field_session['loaded_join_clause'] = $join_clause;
- $where_clause['join_piece'] = join($_SESSION['_AcField'][$requestingPage][$sourceUniqueId]['filters'], ' AND ');
+ /**
+ * verify that this control is indeed allowed to update the other control.
+ * Do this verification by looking at session records.
+ */
+ if (!in_array($this_field_session["unique_id"], $source_field['dependent_fields'])) {
+ throw_error(AcField::ERROR_LOAD_DISALLOWED); //This indicates attempted hacking.
}
- $this_field_session['loaded_pkey'] = $request['primaryInfo'][1];
- }
- else {
- $where_clause[] = $fake_this->adapter->escape_table_name($this_field->bound_table) . '.' . $fake_this->adapter->escape_field_name($this_field->bound_pkey) . ' = ' . $fake_this->adapter->escape_field_value($this_field_session['hardcoded_loads'][$request['primaryInfo'][1]]);
- $this_field_session['loaded_pkey'] = $this_field_session['hardcoded_loads'][$request['primaryInfo'][1]];
- }
- $this_field_session['loaded_where_clause'] = $where_clause;
+
+ $join_clause[] = $source_field['bound_table'] . ' ON ' .
+ $fake_this->adapter->escape_table_name($this_field->bound_table)
+ . "." . $fake_this->adapter->escape_field_name($this_field->bound_pkey)
+ . " = " . $fake_this->adapter->escape_table_name($source_field['bound_table'])
+ . "." . $fake_this->adapter->escape_field_value($source_field["bound_pkey"]);
+
+ //All join clauses need to have INNER JOINs between them
+ if (count($join_clause) > 0) {
+ $join_clause = 'INNER JOIN ' . join($join_clause, ' INNER JOIN ');
+ }
+
+ $this_field_session['loaded_join_clause'] = $join_clause;
+ $where_clause['join_piece'] = join($_SESSION['_AcField'][$requestingPage][$sourceUniqueId]['filters'], ' AND ');
+ }
+ }//</if filtered>
+
+ $this_field_session['loaded_pkey'] = $request['primaryInfo'][1];
} else {
- //The reason we use trigger-error is to allow this informative message to show up in DEV but
- // stifle it to a generic one in production.
- trigger_error('Unknown action type requested in ajax_field: ' . $request['action'], E_USER_ERROR);
+ //Hardcoded Load
+ $where_clause[] = $fake_this->adapter->escape_table_name($this_field->bound_table)
+ . '.' . $fake_this->adapter->escape_field_name($this_field->bound_pkey)
+ . ' = ' . $fake_this->adapter->escape_field_value($this_field_session['hardcoded_loads'][$request['primaryInfo'][1]]);
+
+ $this_field_session['loaded_pkey'] = $this_field_session['hardcoded_loads'][$request['primaryInfo'][1]];
}
+ $this_field_session['loaded_where_clause'] = $where_clause;
+
/*
- * This is where load requests are handled.
- * To Do: Move it all in in a more object oriented fashion.
+ * Generate the actual query
*/
+ $sql = "SELECT $values_clause FROM $table $join_clause WHERE " . join(' AND ', $where_clause);
+ $result = $fake_this->adapter->query_read($sql);
- if (($request['action'] === 'hardcoded_load') || ($request['action'] === 'dynamic_load')) {
- $sql = "SELECT $values_clause FROM $table $join_clause WHERE " . join(' AND ', $where_clause);
- $result = $fake_this->adapter->query_read($sql);
+ /**
+ * Since this is limited by a primary key, it should return exactly one row
+ */
+ if (count($result) !== 1)
+ throw_error("Incorrect number of rows returned from read");
- /**
- * Since this is limited by a primary key, it should return exactly one row
- */
- if (count($result) !== 1)
- throw_error("Incorrect number of rows returned from read");
- $result = array('value' => $result[0]['answer']);
-
- }
+ $result = array('value' => $result[0]['answer']);
- elseif ($request['action'] === 'save') {///////////////////////////////////
- //library isn't currently designed to securely handle a save before a load.
- if (!isset($this_field_session['loaded_where_clause']))
- throw_error('Not Supported');
-
- if (!isset($this_field_session['loaded_join_clause'])) //optional
- $this_field_session['loaded_join_clause'] = '';
-
-
- /**
- * It's crucial that we apply all the limiting filters that restrict what
- * values can be *loaded* into a control to the process of SAVING a control.
- *
- * This is thus stored in the session.
- */
- $sql = "SELECT COUNT(*) as count_rec from $table " . $this_field_session['loaded_join_clause']
- . " WHERE " . join($this_field_session['loaded_where_clause'], " AND ");
-
- $security_check = $fake_this->adapter->query_read($sql);
- if (!$security_check[0]['count_rec'])
- throw_error('Security issue');
- else if ($security_check[0]['count_rec'] > 1) {
- // You probably don't want to do something that affects multiple rows since you are usually operating on primary key.
- //However if you know what you are doing, you can disable this restriction by commenting the following line
- throw_error('Cancelled. Affects multiple rows.');
- }
+ return $result;
+}
- /**
- * Apply save validations
- */
- foreach ($values as $x)
- if (!$theAcField->do_validations($x[1], $this_field_session['loaded_pkey']))
- throw_error('Could not save field: Validation Failed');
-
- /**
- * Perform the actual save
- */
- $sql = "UPDATE $table SET $values_clause WHERE " . join($this_field_session['loaded_where_clause'], " AND ");
- $fake_this->adapter->query_write($sql, 1);
- $result['value'] = "success";
- } else {
- trigger_error("Unknow Action:" . $request['action'], E_USER_ERROR);
- }
+/**
+ * Not implemented. Will allow client side code to request record insertion, in
+ * a verifiable accurate way.
+ */
+function insert_action() {
+// I haven't yet ported this to the new format for this library and thus it is non-functional
+ /* {
+ foreach ($values as $x)
+ {
+ $values_clause1[] = cleanFieldName($x[0]);
+ $values_clause2[] = cleanFieldValue($x[1]);
+ $values_clause = " (" . join(",", $values_clause1) . ") VALUES (" . join(",", $values_clause2) . ") " ;
+ if (isset($where_clause))
+ trigger_error("Cannot use limiting conditions in an insert", E_USER_ERROR );
- return ($result);
+ if (strpos($SECURITY_PERMISSIONS["normal"][$table], "W") === false)
+ trigger_error("Insufficient Permissions to write to table -$table-", E_USER_ERROR );
+ }
+ } */
}
-//
?>
View
5 AliveFields/_internalInclude/ajax_list.php
@@ -61,7 +61,7 @@ function acList_Controller(& $fake_this, $request) {
elseif ($this_field->options_loadability == AcField::LOAD_YES)
; // okay, we can load without filters
else {
- throw_error("Field ($field_unique_id) not loadable.. ");
+ throw_error(AcField::ERROR_LOAD_DISALLOWED);
}
// </ Check Security >
@@ -136,6 +136,9 @@ function acList_Controller(& $fake_this, $request) {
$this_field_session["last_used_query"] = $query;
$query .= " ORDER BY $field2 ";
+ if (!isset($request['max_rows']))
+ $request['max_rows'] = null;
+
$result = $fake_this->adapter->query_read($query, (int) $request['max_rows']);
if (is_null($result))
View
24 AliveFields/_internalInclude/general_functions.php
@@ -106,24 +106,28 @@ function stripslashes_gpc(&$value)
function verify_control_could_contain_value($fake_this, $page, $fieldUniqueId, $value, $field)
{
$test_field = $_SESSION['_AcField'][$page][$fieldUniqueId];
- $this_field = AcField::instance_from_id($fieldUniqueId);
- if (! isset($test_field["last_used_query"]) )
- return false;
-
+ if (! isset($test_field["last_used_query"]) ) {
+ return false;
+ }
if ($field == "pkey")
- $fieldname = $this_field->bound_pkey;
+ $fieldname = $fake_this->bound_pkey;
elseif ($field == "text")
- $fieldname = $this_field->bound_field;
+ $fieldname = $fake_this->bound_field;
elseif ($field == "optionValue")
- $fieldname = $this_field->options_pkey;
+ $fieldname = $fake_this->options_pkey;
else
die("unknown verify type: $field");
//WHat about stuff? which queries are active which filters I mean? All will be used in its last query... Cool.
- $query = $test_field["last_used_query"] . " AND " . $fake_this->adapter->escape_field_name($fieldname) . " = " . $fake_this->adapter->escape_field_value($value);
-
+ $query = $test_field["last_used_query"] . " AND " . $fake_this->adapter->escape_field_name($fieldname) . " = " . $fake_this->adapter->escape_field_value($value);
$result = ($fake_this->adapter->query_read($query, 1));
-
+
+ if (!$result)
+ {
+ echo ($query);
+ die("k");
+
+ }
return $result;
}
View
1 example.php
@@ -110,7 +110,6 @@ function ($new_value) {
<script src="js/controls/AcSelectbox/AcJoinSelectbox.js"></script>
*/
?>
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link link rel="stylesheet" type="text/css" href="css/custom-theme/jquery-ui-1.8.16.custom.css" />
<title>ALive Fields Demo App</title>
View
2 index.html
@@ -22,7 +22,7 @@
</head>
<body>
<div class="right_align">
- <img src='ALfields%20logo.png' />
+ <img src='img/ALfields%20logo.png' />
</div>
<h1>ALive Fields </h1><br />
View
11 jquery.ui.all.css
@@ -1,11 +0,0 @@
-/*
- * jQuery UI CSS Framework 1.8.16
- *
- * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming
- */
-@import "jquery.ui.base.css";
-@import "jquery.ui.theme.css";
View
21 js/controls/AcControls.js
@@ -125,10 +125,8 @@ AcField.prototype.initialize = function(jqElementStr)
return handleError("Control already bound:" + jqElement.selector, jqElement[0]);
this.correspondingElement = jqElement;
- jqElement[0].boundAcControl = this; //not an infinite loop since these are merely pointers.
- //however, this may prevent them from being json Encoded. If this becomes an issue, change it
- // from a pointer to the actual element to a boolean.
- ///*
+ jqElement[0].boundAcControl = this; //Give the HTML ELEMENT a pointer back to this.
+
/**
*On blur, determine if the values have changed. If so call, change handler.
@@ -198,6 +196,9 @@ AcField.prototype.handleKeydown = function()
////////////////////////////////////////////////////////
/** @description This function saves the given field to the database.
+ * on Success flash box green, then call dependent fields
+ * on Failure flash box red, then submit an error to log.
+ *
* @param primaryKeyData This value is used to determine which row in table this value will be saved to.
*/
AcField.prototype.saveField = function()
@@ -217,7 +218,11 @@ AcField.prototype.saveField = function()
type: "POST",
data: {"request": JSON.stringify(information)},
context: this,
- error : function (a, b , c) { if (typeof(window_unloading) == "undefined") handleError(" Saving of field interrupted by leaving page."); },
+ error : function (a, b , c)
+ {
+ if (typeof(window_unloading) == "undefined")
+ handleError(" Saving of field interrupted by leaving page.");
+ },
success: function(data, b, c, d, e)
{
if ((data.substr(0,1) != "[") && (data.substr(0,1) != "{"))
@@ -241,8 +246,7 @@ AcField.prototype.saveField = function()
});
// make ajax request.
- // on Success flash box green, then call dependent fields
- // on Failure flash box red, then submit an error to log.
+
}
@@ -277,9 +281,6 @@ AcField.prototype.loadField = function(primaryKeyData, type, source)
this.setColor("");
this.setBorder("#9999DD");
var theObject = this; // "VAR" is CRUCIAL in this line!
-
- if (this.correspondingField == "")
- return handleError("Cannot load a control that has no fieldname.");
information = {"AcFieldRequest": "loadfield" ,"primaryInfo": [this.pkeyField , primaryKeyData] , "requesting_page" : AcFieldGetThisPage(), "request_field" : this.uniqueId};

0 comments on commit 93f4c20

Please sign in to comment.
Something went wrong with that request. Please try again.