I have created a CheckModulePermission function in my user class which checks a module table to ensure the user has permissions to view the page. Below is the function
public function CheckModulePermissions($moduleId) {
if(isset($_SESSION['userId'])) {
// If the user is admin, allow regardless
if($this->IsAdmin()) {
return true;
}
$sql = "SELECT `userModuleId`
FROM `userModules`
WHERE `userId` = " . $_SESSION['userId'] . "
AND `moduleId` = " . $moduleId . ";";
mysql_select_db(DB_USER_DATABASE_NAME, $this->conn);
$result = mysql_query($sql, $this->conn);
$x = mysql_fetch_row($result);
if($x[0] == 1) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
This works fine in all my pages except one page where it fails . I have a dropdown box and a text box which will be updated depending on the users permission. The user i am logged on as has the permission but the dropdown boxes do not appear.
if(isset($_GET['orderNumber'])) {
// If post is set then update the prima reference and order status
// Only if user has sufficient privileges
if(isset($_POST['orderStatus'])) {
if($user->CheckModulePermissions(11)) {
$cid->UpdateOrderStatus($_GET['orderNumber'], $_POST['orderStatus']);
$cid->UpdateOrderReference($_GET['orderNumber'], $_POST['PReference']);
}
}
if($user->CheckModulePermissions(11)) {
$content .= "<select name='orderStatus'>
<option value='1'";
if($orderDetails['status'] == 1) $content .= " selected='selected'";
$content .= ">Incomplete</option>
<option value='2'";
if($orderDetails['status'] == 2) $content .= " selected='selected'";
$content .= ">Submitted</option>
<option value='3'";
if($orderDetails['status'] == 3) $content .= " selected='selected'";
$content .= ">Processed</option>
</select>";
} else {
if($orderDetails['status'] == 1) $content .= "Incomplete";
if($orderDetails['status'] == 2) $content .= "Submitted";
if($orderDetails['status'] == 3) $content .= "Processed";
}
$content .= "</td>
</tr>
<tr>
<th>Prima Order Number</th>
<td>";
if($user->CheckModulePermissions(11)) {
$content .= "<input type='text' name='pReference' value='" . $orderDetails['PReference'] . "' /></td>
</tr>
<tr>
<td colspan='2'><input type='submit' /></td>
</tr>";
} else {
$content .= $orderDetails['PrimaReference'] . "</td></tr>";
}
$content .= "</table>
</form>
</td>
Is it the logic for the dropdown box where it fails?
Here is a more efficient/readable version of your CheckModulePermissions() method...
public function CheckModulePermissions ($moduleId) {
// Deny immmediately if no userId is set
if (!isset($_SESSION['userId'])) return FALSE;
// If the user is admin, allow regardless
if ($this->IsAdmin()) return TRUE;
// Generate an SQL statement - does this need sanitising?
$sql = "SELECT `userModuleId`
FROM `userModules`
WHERE `userId` = '{$_SESSION['userId']}'
AND `moduleId` = '$moduleId'
LIMIT 1";
// Is this line really necessary? Are you actually working with more than one database?
// Even if you are, it's probably better to do it in the query, like this:
// SELECT whatever FROM DB_USER_DATABASE_NAME.tablename WHERE...
mysql_select_db(DB_USER_DATABASE_NAME, $this->conn);
// Since you only want one row, it's slightly more resource efficient
// to abandon the $result variable
$x = mysql_fetch_row(mysql_query($sql, $this->conn));
// This means the same thing as your if ... else
return $x[0] == 1;
}
...and here is a rewritten version of the HTML generation code.
// Get this once, at the beginning, to minimise SQL traffic
$hasPermissions = $user->CheckModulePermissions(11);
// Uncomment this line to make sure that $user->CheckModulePermissions is returning the value you expect
//var_dump($hasPermissions);
if (isset($_GET['orderNumber'])) {
// If post is set then update the prima reference and order status
// Only if user has sufficient privileges
if (isset($_POST['orderStatus']) && $hasPermissions) {
$cid->UpdateOrderStatus($_GET['orderNumber'], $_POST['orderStatus']);
$cid->UpdateOrderReference($_GET['orderNumber'], $_POST['PReference']);
}
// Map of status numbers to string descriptions
$statusStrs = array(1 => 'Incomplete','Submitted','Processed');
if ($hasPermissions) {
// Generate a <select>
$content .= "<select name='orderStatus'>";
foreach ($statusStrs as $val => $str) {
$content .= "\n<option value='$val'".(($orderDetails['status'] == $val) ? " selected='selected'" : '').">$str</option>";
}
$content .= "\n</select>";
} else {
// Print the current status string
$content .= $statusStrs[$orderDetails['status']];
}
// Close the table cell (layout tables are nasty nasty)
$content .= "</td>
</tr>
<tr>
<th>Prima Order Number</th>
<td>";
if ($hasPermissions) {
// add an input for changing the reference number
$content .= "<input type='text' name='pReference' value='{$orderDetails['PReference']}' /></td>
</tr>
<tr>
<td colspan='2'><input type='submit' /></td>
</tr>";
} else {
// Display the current reference number
$content .= $orderDetails['PrimaReference'] . "</td></tr>";
}
$content .= "</table>
</form>
</td>
I think the most likely cause of your problem is that CheckModulePermissions() is returning FALSE when you expect it to return TRUE. Uncomment the var_dump() line to verify this and we'll take it from there.
Related
I have this function:
function get_content($text_to_match) {
$query = "SELECT * ";
$query .= "FROM table_name ";
$query .= "WHERE one_column_name LIKE '%{$text_to_match}%' OR another_column_name LIKE '%{$text_to_match}%'";
$cont = mysqli_query($connection, $query);
if($content = mysqli_fetch_assoc($cont)) {
return $content;
} else {
return null;
}
}
But when I call it like:
<div>
<?php
for ($i = 1; $i < count(get_content("text_to_match")); $i++) {
echo '<article>' .
'<h3>' . get_content("text_to_match")["string1"] . '</h3>'.
'<p>' . get_content("text_to_match")["string2"] . '</p>' .
'</article>';
}
?>
</div>
I only get the first match in the DB repeated as many times as the number of found items.
Where have I gone wrong?
use this code then fetch data properly
while($content = mysql_fetch_array($cont))
{
return $content;
}
Your logic is at fault. You are calling get_content function to get all matches for the loop, as well as to get individual elements out of the list. This is:
bad logic - the 2nd use case doesn't make sense
excessive - you shouldn't need to run a database query just to output an already retrieved result
What you probably want to do is:
foreach (get_content('text_to_match') as $content) {
echo '<article>';
echo '<h3>' . $content['string1'] . '</h3>';
echo '<p>' . $content['string2'] . '</p>';
echo '</article>';
}
With a few modifications in combination with tips from #Anant and #Unix One's answer, I arrived at this working solution:
Function definition
function get_content($text_to_match, $multiple=false) {
$query = "SELECT * ";
$query .= "FROM table_name ";
$query .= "WHERE one_column_name LIKE '%{$text_to_match}%' OR another_column_name LIKE '%{$text_to_match}%'";
$cont = mysqli_query($connection, $query);
if ($multiple) {
$content_array = [];
while($content = mysqli_fetch_array($cont)) {
$content_array[] = $content;
}
return $content_array;
} else {
if($content = mysqli_fetch_assoc($cont)) {
return $content;
} else {
return null;
}
}
}
Function calls
<?php
/* multiple items */
foreach(get_content("text_to_match", true) as $content) {
echo '<article>' .
'<h3>' . $content["string1"] . '</h3>' .
'<p>' . $content["string2"] . '</p>' .
'</article>';
}
?>
<?php
/* one item */
echo get_content("text_to_match")["string"];
?>
I have 2 pieces of code from a simple plugin that work independently from each other but don't work together.
if(isset($_POST['submit'])){
if(has_presence($_POST['product_name'])){
insert_row_into_table('CAL_products');
show_errors();
if(has_presence($wpdb->last_query)) {
echo "Update Successful";
} else {
echo "Update Failed";
}
} else {
echo "The field 'Product Name' cannot be blank.";
}
}
And this one
$results_array = $wpdb->get_results("SELECT * FROM wpCMS_CAL_products ORDER BY id ASC");
echo build_table_from_results_array($results_array);
The functions are included at the bottom.
The problem I have is that when the page loads there is no $_POST so it skips over the if statement and builds the table. This table builds fine.
When the form is submitted the if statements come back true and the new value is added to the database successfully, but then the table doesn't build until the page is refreshed. If the code to build the table is put at the top above the if statement it builds fine but doesn't include the new value until the page is refreshed.
Is it possible to add a new item to the database table before the results are populated to the HTML table?
function insert_row_into_table($table_name){
global $wpdb;
$prefix = $wpdb->prefix; //Define the wordpress table prefix
$table = $prefix . $table_name; //Build the table name
unset($_POST['submit']);
echo print_r($_POST);
$data = $_POST; //collect the data from post
$wpdb->insert( $table, $data ); //insert data into the table
}
function show_errors(){
echo $wpdb->show_errors();
echo $wpdb->print_error();
}
function has_presence($value) {
return isset($value) && $value !== "";
}
function build_table_from_results_array($results_array) {
$out = "";
$out .= "<table class=\"widefat\">";
$out .= "<thead>";
foreach($results_array[0] as $key => $element) {
if($key == "id") {
$out .= "<th class=\"id-column\">";
$out .= strtoupper($key);
$out .= "</th>";
} else {
$out .= "<th>";
$out .= ucwords(str_replace("_", " ", $key));
$out .= "</th>";
}
}
$out .= "</thead>";
$out .= "<tbody>";
$i = 0;
foreach($results_array as $key => $element){
if($i % 2 === 0) $extraclass= "alternate";
$out .= "<tr class=\"$extraclass\">";
$i++;
$extraclass="";
foreach($element as $subkey => $subelement){
$out .= "<td>$subelement</td>";
}
$out .= "<td>EDIT</td>";
$out .= "</tr>";
}
$out .= "</tbody>";
$out .= "</table>";
return $out;
}
A general pattern for this type of page is Post-Redirect-Get. You could, for instance, pull the if(isset($_POST['submit'])) block out into a separate file called processForm.php. The form's action parameter is changed to processForm.php. The form sends $_POST data to processForm which inserts the new database records, and processForm in turn redirects the user back to the original page which gets the results.
If you want a one-page solution using the above code, add this code at the very top of the file, before you output anything at all. This starts the output buffer, which is usually necessary if you want to use the header() command to redirect.
ob_start();
Then edit the if(isset) block:
if(isset($_POST['submit'])){
if(has_presence($_POST['product_name'])){
insert_row_into_table('CAL_products');
show_errors();
if(has_presence($wpdb->last_query)) {
echo "Update Successful";
header("Location: index.php"); //change index.php to the current page
//header("Location: ".$from); //or use a variable
} else {
echo "Update Failed";
}
} else {
echo "The field 'Product Name' cannot be blank.";
}
}
Finally, add this at the very end of the script to close the output buffer:
ob_end_flush();
Essentially, this code refreshes the page on success after the new entries are inserted into the database. This should allow your table to include the new records.
So, I asked this question earlier this week, and #newfurniturey helped me out, but now I have a new problem: I'd like to be able to put devices in that span more than one U (hence, the usize column in the devices db table) - some devices can span take up half a cabinet. Also, I'd like to be able to mark devices as being in the front or rear of the cabinet, but that should be simple enough for me to figure out.
Here's the working code (see old question for db setup) for just 1U devices:
<SCRIPT LANGUAGE="JavaScript" type="text/javascript">
<!--
function clickHandler(e)
{
var targetId, srcElement, targetElement;
if (window.event) e = window.event;
srcElement = e.srcElement? e.srcElement: e.target;
if (srcElement.className == "Outline")
{
targetId = srcElement.id + "d";
targetElement = document.getElementById(targetId);
if (targetElement.style.display == "none")
{
targetElement.style.display = "";
srcElement.src = "images/minus.gif";
}
else
{
targetElement.style.display = "none";
srcElement.src = "images/plus.gif";
}
}
}
document.onclick = clickHandler;
-->
</SCRIPT>
<noscript>You need Javascript enabled for this page to work correctly</noscript>
<?
function sql_conn()
{
$username="root";
$password="root";
$database="racks";
$server="localhost";
#mysql_connect($server,$username,$password) or die("<h2 align=\"center\" class=\"red\">[<img src=\"images/critical.gif\" border=\"0\">] Unable to connect to $server [<img src=\"images/critical.gif\" border=\"0\">]</h2>");
#mysql_select_db($database) or die("<h2 align=\"center\" class=\"red\">[<img src=\"images/critical.gif\" border=\"0\">] Unable to select $database as a database [<img src=\"images/critical.gif\" border=\"0\">]</h2>");
}
sql_conn();
$sql_datacenters="SELECT * FROM `datacenters`";
$result_datacenters=mysql_query($sql_datacenters);
$j=0;
echo "<table border='1' style='float:left;'>";
while ($datacenters_sqlrow=mysql_fetch_array($result_datacenters))
{
echo "<tr><td>";
echo "<h2 class='black' align='left'>";
echo "<IMG SRC='images/plus.gif' ID='Out" . $j . "' CLASS='Outline' STYLE='cursor:hand;cursor:pointer'>"; // fancy icon for expanding-collapsing section
echo " " . $datacenters_sqlrow['rack'] . ": " . $datacenters_sqlrow['cagenum'] . "</h2>"; // datacenter name and cage number
echo "<div id=\"Out" . $j . "d\" style=\"display:none\">"; // opening of div box for section that is to be expanded-collapsed
echo $datacenters_sqlrow['notes'] . "<br /><br />"; // datacenter notes
$sql_cabinets="SELECT * FROM `cabinets` WHERE `datacenter` = '$datacenters_sqlrow[0]' ORDER BY `cabinetnumber` ASC";
$result_cabinets=mysql_query($sql_cabinets);
while ($cabinets_sqlrow=mysql_fetch_array($result_cabinets))
{
$sql_devices="SELECT * FROM `devices` WHERE `datacenter` = '$datacenters_sqlrow[0]' AND `cabinet` = '$cabinets_sqlrow[1]' ORDER BY `ustartlocation` ASC";
$result_devices=mysql_query($sql_devices);
echo "<table border='1' style='float:left;'>"; // opening of table for all cabinets in datacenter
echo "<tr><td colspan='2' align='middle'>" . $cabinets_sqlrow[1] . "</td></tr>"; // cabinet number, spans U column and device name column
$devices = array();
while($row = mysql_fetch_array($result_devices)) {
$devices[$row['ustartlocation']] = $row['devicename'];
}
for ($i = 0; $i < $cabinets_sqlrow[2]; $i++) // iterates through number of U in cabinet
{
$u = $cabinets_sqlrow[2] - $i; // subtracts current $i value from number of U in cabinet since cabinets start their numbers from the bottom up
echo "<tr>";
echo "<td width='15px' align='right'>$u</td>"; // U number
echo (isset($devices[$u]) ? "<td width='150px' align='middle'>$devices[$u]</td>" : "<td width='150px' align='middle'>empty</td>");
echo "</tr>";
}
echo "</table>"; // closes table opened earlier
}
echo "</td></tr>";
echo "</div>"; // close for div box that needs expanding-collapsing by fancy java
$j++; // iteration for the fancy java expand-collapse
}
echo "</table>";
mysql_close();
?>
Based on your previous question, each ustartlocation is unique (hence why you can use it as an index in your $devices array). Using this same concept, you could populate the $devices array from "ustartlocation to (ustartlocation + (usize - 1))".
$devices = array();
while($row = mysql_fetch_array($result_devices)) {
$endLocation = ($row['ustartlocation'] + ($row['usize'] - 1));
for ($location = $row['ustartlocation']; $location <= $endLocation; $location++) {
$devices[$location] = $row['devicename'];
}
}
Because your display-loop already iterates through each U and displays the device assigned, you shouldn't need to modify any other portion. However, the caveat to this is that the device-name will repeat for every U instead of span it. To span it, we'll need to do a little more work.
To start, we could just store the usize in the $devices array instead of filling in each individual position. Also, to prevent a lot of extra work/calculations later, we'll also store a "placeholder" device for each additional position.
while($row = mysql_fetch_array($result_devices)) {
// get the "top" location for the current device
$topLocation = ($row['ustartlocation'] + $row['usize'] - 1);
// populate the real position
$devices[$topLocation] = $row;
// generate a list of "placeholder" positions
for ($location = ($topLocation - 1); $location >= $row['ustartlocation']; $location--) {
$devices[$location] = 'placeholder';
}
}
Next, in your display-loop, you will check if the current position is a placeholder or not (if so, just display the U and do nothing for the device; if it isn't, display the device, or 'empty'). To achieve the "span" effect for each device, we'll set the cell's rowspan equal to the device's usize. If it's 1, it will be a single cell; 2, it will span 2 rows, etc (this is why "doing nothing" for the device on the placeholder-rows will work):
for ($i = 0; $i < $cabinets_sqlrow[2]; $i++) {
$u = $cabinets_sqlrow[2] - $i;
echo "<tr>";
echo '<td width="15px" align="right">' . $u . '</td>';
if (isset($devices[$u])) {
// we have a "device" here; if it's a "placeholder", do nothing!
if ($devices[$u] != 'placeholder') {
echo '<td width="150px" align="middle" rowspan="' . $devices[$u]['usize'] . '">' . $devices[$u]['devicename'] . '</td>';
}
} else {
echo '<td width="150px" align="middle">empty</td>';
}
echo "</tr>";
}
So, as it can be seen - the first method above that simply repeats the device for each U it spans is much simpler. However, the second method will present a more user-friendly display. It's your preference to which method you want to use and which one you think will be more maintainable in the future.
UPDATE (code-fix & multi-direction spanning)
I didn't realize that your table was being built in descending-order so I had the ustartlocation as the "top location" which caused an erroneous row/cell shift. I've fixed the code above to properly set a "top location" based on the ustartlocation and usize for each device that will fix that issue.
Alternatively, as direction may or may not be important, I've customized the $devices-populating loop (below) to support creating a row-span that goes either upwards or downwards, completely depending on the flag you specify. The only code you'll need to change (if you already have the customized display-loop from above) would be the while loop that populates $devices:
$spanDevicesUpwards = true;
while($row = mysql_fetch_array($result_devices)) {
if ($row['usize'] == 1) {
$devices[$row['ustartlocation']] = $row;
} else {
$topLocation = ($spanDevicesUpwards ? ($row['ustartlocation'] + $row['usize'] - 1) : $row['ustartlocation']);
$bottomLocation = ($spanDevicesUpwards ? $row['ustartlocation'] : ($row['ustartlocation'] - $row['usize'] + 1));
$devices[$topLocation] = $row;
for ($location = ($topLocation - 1); $location >= $bottomLocation; $location--) {
$devices[$location] = 'placeholder';
}
}
}
This new block of code will, if the usize spans more than 1, determine the "top cell" and "bottom cell" for the current device. If you're spanning upwards, the top-cell is ustartlocation + usize - 1; if you're spanning downwards, it's simply ustartlocation. The bottom-location is also determined in this manner.
Hoping this will work for you..........for front/rear you can name you device as SERVER3/front or SERVER3/rear:
<SCRIPT LANGUAGE="JavaScript" type="text/javascript">
<!--
function clickHandler(e)
{
var targetId, srcElement, targetElement;
if (window.event) e = window.event;
srcElement = e.srcElement? e.srcElement: e.target;
if (srcElement.className == "Outline")
{
targetId = srcElement.id + "d";
targetElement = document.getElementById(targetId);
if (targetElement.style.display == "none")
{
targetElement.style.display = "";
srcElement.src = "images/minus.gif";
}
else
{
targetElement.style.display = "none";
srcElement.src = "images/plus.gif";
}
}
}
document.onclick = clickHandler;
-->
</SCRIPT>
<noscript>You need Javascript enabled for this page to work correctly</noscript>
<?
function sql_conn()
{
$username="root";
$password="root";
$database="racks";
$server="localhost";
#mysql_connect($server,$username,$password) or die("<h2 align=\"center\" class=\"red\">[<img src=\"images/critical.gif\" border=\"0\">] Unable to connect to $server [<img src=\"images/critical.gif\" border=\"0\">]</h2>");
#mysql_select_db($database) or die("<h2 align=\"center\" class=\"red\">[<img src=\"images/critical.gif\" border=\"0\">] Unable to select $database as a database [<img src=\"images/critical.gif\" border=\"0\">]</h2>");
}
sql_conn();
$sql_datacenters="SELECT * FROM `datacenters`";
$result_datacenters=mysql_query($sql_datacenters);
$j=0;
echo "<table border='1' style='float:left;'>";
while ($datacenters_sqlrow=mysql_fetch_array($result_datacenters))
{
echo "<tr><td>";
echo "<h2 class='black' align='left'>";
echo "<IMG SRC='images/plus.gif' ID='Out" . $j . "' CLASS='Outline' STYLE='cursor:hand;cursor:pointer'>"; // fancy icon for expanding-collapsing section
echo " " . $datacenters_sqlrow['rack'] . ": " . $datacenters_sqlrow['cagenum'] . "</h2>"; // datacenter name and cage number
echo "<div id=\"Out" . $j . "d\" style=\"display:none\">"; // opening of div box for section that is to be expanded-collapsed
echo $datacenters_sqlrow['notes'] . "<br /><br />"; // datacenter notes
$sql_cabinets="SELECT * FROM `cabinets` WHERE `datacenter` = '$datacenters_sqlrow[0]' ORDER BY `cabinetnumber` ASC";
$result_cabinets=mysql_query($sql_cabinets);
while ($cabinets_sqlrow=mysql_fetch_array($result_cabinets))
{
$sql_devices="SELECT * FROM `devices` WHERE `datacenter` = '$datacenters_sqlrow[0]' AND `cabinet` = '$cabinets_sqlrow[1]' ORDER BY `ustartlocation` ASC";
$result_devices=mysql_query($sql_devices);
echo "<table border='1' style='float:left;'>"; // opening of table for all cabinets in datacenter
echo "<tr><td colspan='2' align='middle'>" . $cabinets_sqlrow[1] . "</td></tr>"; // cabinet number, spans U column and device name column
$devices = array();
$devices_size=array();
while($row = mysql_fetch_array($result_devices)) {
$devices[$row['ustartlocation']] = $row['devicename'];
//$devices_size[$row['ustartlocation']+$row['usize']-1] = $row['usize'];
$devices_size[$row['ustartlocation']] = $row['usize'];
}
$start="";
$new="";
for ($i = 0; $i < $cabinets_sqlrow[2]; $i++) // iterates through number of U in cabinet
{
$u = $cabinets_sqlrow[2] - $i; // subtracts current $i value from number of U in cabinet since cabinets start their numbers from the bottom up
echo "<tr>";
echo "<td width='15px' align='right'>$u</td>"; // U number
$rowspan=$devices_size[$u];
//$rowspan1=$
if($rowspan>1)
{
$start=$u;
$new=$u-$rowspan+1;
echo (isset($devices[$u]) ? "<td width='150px' align='middle' rowspan='".$rowspan."'>$devices[$u]</td>" : "<td width='150px' align='middle' rowspan='".$rowspan."'>$devices[$new]</td>");
}
else{
if($u<=$start && $u>=$new)
{
}
else
{
echo (isset($devices[$u]) ? "<td width='150px' align='middle' >$devices[$u]</td>" : "<td width='150px' align='middle'>empty".$row."".$u."</td>");
}
}
echo "</tr>";
}
echo "</table>"; // closes table opened earlier
}
echo "</td></tr>";
echo "</div>"; // close for div box that needs expanding-collapsing by fancy java
$j++; // iteration for the fancy java expand-collapse
}
echo "</table>";
mysql_close();
?>
I have some problems with displaying ÅÄÖ in jcart, I'm not very good at explaining but if you look here you'll see what I mean.
At first it all seems to work, but if you update the page or go to the checkout it doesn't. If you press "Ta bort" or add another item after updating the characters will be displayed correctly again. I use UTF-8 as charset and I've tried ISO-8859-1 which use to fix these problems, but instead it shows another symbol. Don't know exactly where the problem is so please tell me, if you have a clue, what you need more information about.
Looking at the demo may give you some ideas? Thanks!
To show the cart I have this: <?php $jcart->display_cart();?>
And here's some code from jcart.php (included file):
/**
* Process and display cart
*/
public function display_cart() {
$config = $this->config;
$errorMessage = null;
// Simplify some config variables
$checkout = $config['checkoutPath'];
$priceFormat = $config['priceFormat'];
$id = $config['item']['id'];
$name = $config['item']['name'];
$price = $config['item']['price'];
$qty = $config['item']['qty'];
$url = $config['item']['url'];
$add = $config['item']['add'];
// Use config values as literal indices for incoming POST values
// Values are the HTML name attributes set in config.json
$id = $_POST[$id];
$name = $_POST[$name];
$price = $_POST[$price];
$qty = $_POST[$qty];
$url = $_POST[$url];
// Optional CSRF protection, see: http://conceptlogic.com/jcart/security.php
$jcartToken = $_POST['jcartToken'];
// Only generate unique token once per session
if(!$_SESSION['jcartToken']){
$_SESSION['jcartToken'] = md5(session_id() . time() . $_SERVER['HTTP_USER_AGENT']);
}
// If enabled, check submitted token against session token for POST requests
if ($config['csrfToken'] === 'true' && $_POST && $jcartToken != $_SESSION['jcartToken']) {
$errorMessage = 'Invalid token!' . $jcartToken . ' / ' . $_SESSION['jcartToken'];
}
// Sanitize values for output in the browser
$id = filter_var($id, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW);
$name = filter_var($name, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW);
$url = filter_var($url, FILTER_SANITIZE_URL);
// Round the quantity if necessary
if($config['decimalPlaces'] === true) {
$qty = round($qty, $config['decimalPlaces']);
}
// Add an item
if ($_POST[$add]) {
$itemAdded = $this->add_item($id, $name, $price, $qty, $url);
// If not true the add item function returns the error type
if ($itemAdded !== true) {
$errorType = $itemAdded;
switch($errorType) {
case 'qty':
$errorMessage = $config['text']['quantityError'];
break;
case 'price':
$errorMessage = $config['text']['priceError'];
break;
}
}
}
// Update a single item
if ($_POST['jcartUpdate']) {
$itemUpdated = $this->update_item($_POST['itemId'], $_POST['itemQty']);
if ($itemUpdated !== true) {
$errorMessage = $config['text']['quantityError'];
}
}
// Update all items in the cart
if($_POST['jcartUpdateCart'] || $_POST['jcartCheckout']) {
$cartUpdated = $this->update_cart();
if ($cartUpdated !== true) {
$errorMessage = $config['text']['quantityError'];
}
}
// Remove an item
/* After an item is removed, its id stays set in the query string,
preventing the same item from being added back to the cart in
subsequent POST requests. As result, it's not enough to check for
GET before deleting the item, must also check that this isn't a POST
request. */
if($_GET['jcartRemove'] && !$_POST) {
$this->remove_item($_GET['jcartRemove']);
}
// Empty the cart
if($_POST['jcartEmpty']) {
$this->empty_cart();
}
// Determine which text to use for the number of items in the cart
$itemsText = $config['text']['multipleItems'];
if ($this->itemCount == 1) {
$itemsText = $config['text']['singleItem'];
}
// Determine if this is the checkout page
/* First we check the request uri against the config checkout (set when
the visitor first clicks checkout), then check for the hidden input
sent with Ajax request (set when visitor has javascript enabled and
updates an item quantity). */
$isCheckout = strpos(request_uri(), $checkout);
if ($isCheckout !== false || $_REQUEST['jcartIsCheckout'] == 'true') {
$isCheckout = true;
}
else {
$isCheckout = false;
}
// Overwrite the form action to post to gateway.php instead of posting back to checkout page
if ($isCheckout === true) {
// Sanititze config path
$path = filter_var($config['jcartPath'], FILTER_SANITIZE_URL);
// Trim trailing slash if necessary
$path = rtrim($path, '/');
$checkout = $path . '/gateway.php';
}
// Default input type
// Overridden if using button images in config.php
$inputType = 'submit';
// If this error is true the visitor updated the cart from the checkout page using an invalid price format
// Passed as a session var since the checkout page uses a header redirect
// If passed via GET the query string stays set even after subsequent POST requests
if ($_SESSION['quantityError'] === true) {
$errorMessage = $config['text']['quantityError'];
unset($_SESSION['quantityError']);
}
////////////////////////////////////////////////////////////////////////
// Output the cart
// Return specified number of tabs to improve readability of HTML output
function tab($n) {
$tabs = null;
while ($n > 0) {
$tabs .= "\t";
--$n;
}
return $tabs;
}
// If there's an error message wrap it in some HTML
if ($errorMessage) {
$errorMessage = "<p id='jcart-error'>$errorMessage</p>";
}
// Display the cart header
echo tab(1) . "$errorMessage\n";
echo tab(1) . "<form method='post' action='$checkout'>\n";
echo tab(2) . "<fieldset>\n";
echo tab(3) . "<input type='hidden' name='jcartToken' value='{$_SESSION['jcartToken']}' />\n";
echo tab(3) . "<table border='0'>\n";
echo tab(4) . "<thead>\n";
echo tab(5) . "<tr>\n";
echo tab(6) . "<th colspan='3'>\n";
echo tab(7) . "<div align='center'><span style='font-size:24px;' id='jcart-title'><br />VARUKORG</span> ($this->itemCount $itemsText) </div>\n";
echo tab(6) . "</th>\n";
echo tab(5) . "</tr>". "\n";
echo tab(4) . "</thead>\n";
// Display the cart footer
echo tab(4) . "<tfoot>\n";
echo tab(5) . "<tr>\n";
echo tab(6) . "<th colspan='3'>\n";
// If this is the checkout hide the cart checkout button
if ($isCheckout !== true) {
if ($config['button']['checkout']) {
$inputType = "image";
$src = " src='jcart/images/checkout.gif' alt='{$config['text']['checkout']}' title='' ";
}
echo tab(7) . "<input type='$inputType' $src id='jcart-checkout' name='jcartCheckout' class='jcart-button' value='{$config['text']['checkout']}' /> \n";
}
echo tab(7) . "<span id='jcart-subtotal'>{$config['text']['subtotal']}: <strong>" . number_format($this->subtotal, $priceFormat['decimals'], $priceFormat['dec_point'], $priceFormat['thousands_sep']) . " </strong></span>\n";
echo tab(6) . "</th>\n";
echo tab(5) . "</tr>\n";
echo tab(4) . "</tfoot>\n";
echo tab(4) . "<tbody>\n";
// If any items in the cart
if($this->itemCount > 0) {
// Display line items
foreach($this->get_contents() as $item) {
echo tab(5) . "<tr>\n";
echo tab(6) . "<td class='jcart-item-qty'>\n";
echo tab(7) . "<input name='jcartItemId[]' type='hidden' value='{$item['id']}' />\n";
echo tab(7) . "<input id='jcartItemQty-{$item['id']}' name='jcartItemQty[]' size='1' style='margin:0;padding:0;width:20px;' type='text' value='{$item['qty']}' />\n";
echo tab(6) . "</td>\n";
echo tab(6) . "<td class='jcart-item-name'>\n";
if ($item['url']) {
echo tab(7) . "<a href='{$item['url']}'>{$item['name']}</a>\n";
}
else {
echo tab(7) . $item['name'] . "\n";
}
echo tab(7) . "<input name='jcartItemName[]' type='hidden' value='{$item['name']}' />\n";
echo tab(6) . "</td>\n";
echo tab(6) . "<td class='jcart-item-price'>\n";
echo tab(7) . "<span>" . number_format($item['subtotal'], $priceFormat['decimals'], $priceFormat['dec_point'], $priceFormat['thousands_sep']) . "</span><input name='jcartItemPrice[]' type='hidden' value='{$item['price']}' />\n";
echo tab(7) . "<a class='jcart-remove' href='?jcartRemove={$item['id']}'>{$config['text']['removeLink']}</a>\n";
echo tab(6) . "</td>\n";
echo tab(5) . "</tr>\n";
}
}
Ok, I am programming a website and I need to do a lot of html forms everywhere. How can I reduce amount of my time doing that? Any ideas? I guess it should be done with functions.
I don't use neither any frameworks nor OOP yet.
Thank you very much.
Please google "Zen Coding". I think it is what you want. For example:
If you input div#content>h1+p , the following html will be generated:
<div id="content">
<h1></h1>
<p></p>
</div>
Zen Coding is supported by a lot of editors.
Unfortunately, there is no magic FormBuilder::readMyMind() function yet, so you will spend some time on it. Here is some FormBuilders you can use without having to use a framework:
http://pear.php.net/package/HTML_QuickForm2
http://pear.php.net/package/DB_DataObject_FormBuilder
http://framework.zend.com/manual/en/zend.form.html
Note that Zend_Form is part of Zend Framework, but can be used standalone. It does have a number of dependencies on other ZF components though.
My suggestion is to start using a framework sooner as you'll find a lot of your work is already done for you. CodeIgniter or Zend aren't bad ones. If not I'd write a few classes myself that given a number of parameters can render the html needed. Personally getting a framework is a much more compelling choice in the long run.
May be have a look at
http://pear.php.net/package/HTML_QuickForm2
The greater the abstraction (the easier it is to use) then the less control your going to have over the final output. So it may depend on how complex your forms are going to be that will determine the tools you can use.
I wrote a small class to to create a form based on a DB table, a few years ago.
Here is a method to grab all the fields & field types from a database table:
public function getDatabaseFields($db_name, $tbl, $ignoredFields)
{
$db = mysqli_select_db($this->connect, $db_name);
$sql = "DESCRIBE $tbl";
$result = mysqli_query($this->connect, $sql);
if ($result !== false)
{
$i = 0;
while ($row = mysqli_fetch_array($result, MYSQL_ASSOC))
{
if (!in_array($row[Field], $ignoredFields))
{
$formItems[$i][lbl] = $row[Field];
$formItems[$i][type] = $row[Type];
$formItems[$i][nul] = $row["Null"];
}
$i++;
}
return $formItems;
}
else
{
return false;
}
}
And here is a method to generate forms based on that data:
/**
* This function gets the details of a table and
* creates a form to insert values in that table
* $ignoredFields is an array of fields which should not be in the form
* $specialFields contain complete fields ready to output, (useful if you need fields not in the table)
* $existingData are data that should be displayed in the fields
* $options[formTitle] displays a title above the form in a separate <div>
* $options[errors][fieldName] display the field's label in bold red letters
* $options[hidden][fieldName] set field as hidden and the value is $options[hidden][fieldName][value]
* #param <string> $db_name
* #param <string> $tbl
* #param <array> $ignoredFields
* #param <array> $specialFields
* #param <array> $existingData
* #param <array> $options
*/
function form_db_table($db_name, $tbl, $ignoredFields, $specialFields, $existingData, $options)
{
# Get all the database fields that must be filled out.
$formItems = $this->getDatabaseFields($db_name, $tbl, $ignoredFields);
# Generate the form fields and load them in variables
foreach ($formItems as $key=>$value)
{
# $fieldName is the actual field name in the database.
# $fieldLbl is the name displayed in the form before the field
$fieldName = $value[lbl];
$pattern = array('/([a-z])([A-Z])/','/[_-]/');
$replacement = array('$1 $2', ' ');
$fieldLbl = ucfirst(strtolower(preg_replace($pattern, $replacement, $fieldName)));
# if $fieldName is in $options[hidden], an hidden input is created
if (is_array($options[hidden]))
{
if (array_key_exists($fieldName, $options[hidden]))
{
$val = $options[hidden][$fieldName];
$formEntries .= "<input type='hidden' name='$fieldName' value='$val' />";
continue;
}
}
if($value[nul] == "YES")
{
$mandatory = "";
}
else
{
$mandatory = "*";
$mandatoryFields .= $value[lbl] . ";";
}
// from type, decide which form item to use: varchar = <input> ...
if (stripos($value[type],"varchar") !== false)
{
$varcharLimit = substr($value[type], 8, -1);
if ($varcharLimit < 71)
{
$inputItem = "<input type=\"text\" size=\"38\" maxlength=\"$varcharLimit\"".
" name=\"$fieldName\" value=\"$existingData[$fieldName]\" class=\"entryField\"/>";
}
else
{
$inputItem = "<textarea cols=\"35\" rows=\"3\" wrap=\"VIRTUAL\"" .
" name=\"$fieldName\" class=\"entryField\">$existingData[$fieldName]</textarea>";
}
}
else if (stripos($value[type],"text") !== false)
{
$inputItem = "<textarea cols=\"35\" rows=\"8\" wrap=\"VIRTUAL\"" .
" name=\"$fieldName\" class=\"entryField\">$existingData[$fieldName]</textarea>";
}
else if (stripos($value[type],"date") !== false)
{
$inputItem = "<input type=\"text\" size=\"38\" maxlength=\"50\"".
" name=\"$fieldName\" value=\"$existingData[$fieldName]\" class=\"entryField\"/>";
}
else if (stripos($value[type],"enum") !== false)
{
$inputItem = "<select size=\"1\" name=\"$fieldName\">\r\n";
if (isset($existingData[$fieldName]))
{
$inputItem .= "<option value=\"$existingData[$fieldName]\">$existingData[$fieldName]</option>";
}
$enumVal = explode(",",substr($value[type], 6, -1));
foreach($enumVal as $key => $value)
{
$val= trim(str_replace("'", "", $value));
$inputItem .= "<option value=\"$val\">$val</option>";
}
$inputItem .= "</select>";
}
## !!! COMPLETE THE LIST OF TYPES !!!
$error = $options[error][$fieldName];
$formEntries .= "<div class=\"entry\">\r\n";
$formEntries .= "<label class=\"lbl_regular\" style=\"$error\">\r\n";
$formEntries .= "$fieldLbl$mandatory</label>\r\n$inputItem \r\n";
$formEntries .= "</div>\r\n";
}
# Sends the list of mandatory fields
if ($mandatoryFields != "")
{
$mandatoryFields = substr($mandatoryFields, 0, -1);
//- Explode to determine which fields can't be blank -\\
$mandatoryFields = "<input type='hidden' name='mandatory' value='$mandatoryFields'>\r\n";
}
# Extract special fields - fields and labels ready for output
if (is_array($specialFields))
{
foreach ($specialFields as $key=>$value)
{
if($value[where]="before")
{
$specFieldsBefore .= "$value[openField] $value[lbl] $value[field]\r\n $value[closeField] \r\n";
}
else
{
$specFieldsAfter .= "$value[openField] $value[lbl] $value[field]\r\n $value[closeField] \r\n";
}
}
}
# Error message
if (isset($options[errMsg]))
{
echo "<div class=\"errorMsg\">$options[errMsg]</div>";
}
# Output the top of the form
echo $this->formTag;
if (isset($options[formTitle]))
{
echo "\r\n<div class=\"formTitle\">$options[formTitle]</div>\r\n";
}
echo "<fieldset class=\"formFieldSet\">\r\n";
#output the the actual fields
echo $mandatoryFields;
echo $specFieldsBefore;
echo $formEntries;
echo $specFieldsAfter;
# Close fieldset, add a validate button and close the form
echo "</fieldset>";
echo "<center><input type=\"submit\" value=\"Submit\" name=\"submit\" /></center>";
echo "</form>";
}
No doubt there must be more elegant solutions out there, but if the form's purpose is to fill out a database table, it makes it pretty easy to generate a form.