+++ /dev/null
-<?php\r
-\r
-/**\r
- * A class that implements the DB interface for Postgres\r
- * Note: This class uses ADODB and returns RecordSets.\r
- *\r
- * $Id: Postgres.php,v 1.1 2002/02/11 09:32:47 chriskl Exp $\r
- */\r
-\r
-include_once('ADODB_base.pclass');\r
-\r
-class Postgres extends BaseDB {\r
-\r
- function Postgres() {\r
- $this->User = 'auadmin';\r
- $this->Password = 'bfd12hutz';\r
-\r
- $this->BaseDB();\r
- }\r
-\r
- // Flag functions\r
-\r
- /**\r
- * Retrieves the flags of the specified user\r
- * @param $user_id The ID of the user\r
- * @param $values (optional) Return array as values, rather than keys\r
- * @return An array containing the flag names as it keys with values of true\r
- */\r
- function &getUserFlags($user_id, $values = false) {\r
- $this->clean($meal_id);\r
- $sql = "SELECT fl.name FROM users_flags uf, medidiets_flags fl WHERE uf.flag_id = fl.flag_id AND uf.user_id = '{$user_id}'";\r
- $rs = $this->selectSet($sql);\r
-\r
- $flags = array();\r
- while (!$rs->EOF) {\r
- if ($values)\r
- $flags[] = $rs->f['name'];\r
- else\r
- $flags[$rs->f['name']] = true;\r
- $rs->moveNext();\r
- }\r
-\r
- return $flags;\r
- }\r
-\r
- /**\r
- * Retrieves a user's profile and plan joined\r
- * @param $user_id The ID of the user whose data is to be returned\r
- * @return A recordset\r
- */\r
- function &getProfileAndPlan($user_id) {\r
- $this->clean($user_id);\r
-\r
- $sql = "SELECT * FROM users_profiles_tmp up, medidiets_plans mp WHERE up.user_id='$user_id' AND up.plan_id=mp.plan_id";\r
-\r
- return $this->selectSet($sql);\r
- }\r
-\r
- // Plan functions\r
-\r
- /**\r
- * Returns all existing plans\r
- * @return A recordset\r
- */\r
- function &getPlans() {\r
- $sql = "SELECT * FROM medidiets_plans ORDER BY calories";\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /*\r
- * Finds a meal plan that matches the given number of calories most closely\r
- * @param $cals The number of calories the plan should be\r
- * @return (array) The ID of the plan found, and the actual cals\r
- */\r
- function &findPlan($cals) {\r
- $this->clean($cals);\r
-\r
- $sql = "SELECT plan_id, calories, ABS(calories::numeric - '$cals') AS diff FROM medidiets_plans ORDER BY diff LIMIT 1";\r
- $rs = $this->selectSet($sql);\r
-\r
- return array($rs->f['plan_id'], $rs->f['calories']);\r
- }\r
-\r
- /*\r
- * Finds all meals that adhere to the given options, randomly ordered\r
- * @param $cals The number of calories the plan should be\r
- * @param $when_id The meal of the day to find meals for\r
- * @param $flags An array of flag names to be excluded\r
- * @param $names (optional) Specify whether to return names as well, sorted\r
- * @return A recordset\r
- */\r
- function &findMeals($cals, $when_id, $flags, $names = false) {\r
- $this->clean($cals);\r
- $this->clean($when_id);\r
- $flag_str = implode("','", $flags);\r
-\r
- if ($names) {\r
- $params = 'meal_id, name';\r
- $order = 'name';\r
- }\r
- else {\r
- $params = 'meal_id';\r
- $order = 'RANDOM()';\r
- }\r
-\r
- $sql = "\r
- SELECT \r
- {$params}\r
- FROM \r
- medidiets_meals mm\r
- WHERE \r
- mm.calories='{$cals}'\r
- AND mm.when_id='{$when_id}'\r
- AND mm.visible\r
- AND NOT mm.pending\r
- AND mm.meal_id NOT IN (\r
- SELECT \r
- DISTINCT (meal_id)\r
- FROM \r
- medidiets_flags_map mfp, medidiets_flags mf \r
- WHERE\r
- mfp.flag_id=mf.flag_id\r
- AND mf.name IN ('{$flag_str}')\r
- )\r
- ORDER BY {$order}\r
- ";\r
-\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /*\r
- * Inserts meals into a range of dates for a user\r
- * @param $user_id The ID of the user we're inserting for\r
- * @param $start_date The date at which to start the insertion\r
- * @param $no_days The number of days to insert\r
- * @return 0 success\r
- * @return -1 transaction error\r
- * @return -2 profile/plan retrieval error\r
- * @return -3 meal list retrieval error\r
- * @return -4 insertion failure\r
- * @@ What happens if no breakfasts could be found?!?!?\r
- */\r
- function createMealPlan($user_id, $start_date, $no_days) {\r
- global $defaultCountryCode;\r
-\r
- // begin transaction\r
- $status = $this->beginTransaction();\r
- if ($status != 0) return -1;\r
-\r
- // Get user data, joined with plan data?\r
- $data = &$this->getProfileAndPlan($user_id);\r
- $data->f['seasonal'] = $this->phpBool($data->f['seasonal']);\r
- $flags = &$this->getUserFlags($user_id, true);\r
- \r
- // Seasonal menus\r
- if ($data->f['seasonal']) {\r
- if ($defaultCountryCode == 'AU')\r
- $is_summer = in_array(date('m'), array(10, 11, 12, 1, 2, 3));\r
- else\r
- $is_summer = in_array(date('m'), array(4, 5, 6, 7, 8, 9));\r
-\r
- if ($is_summer) $flags[] = 'NOT_SUMMER';\r
- else $flags[] = 'NOT_WINTER';\r
- }\r
-\r
- // Convenience\r
- $b_flags = $flags;\r
- if ($data->f['mp_breakfast'] == 'C') $b_flags[] = 'NOT_CONVENIENT';\r
- $l_flags = $flags;\r
- if ($data->f['mp_lunch'] == 'C') $l_flags[] = 'NOT_CONVENIENT';\r
- $d_flags = $flags;\r
- if ($data->f['mp_dinner'] == 'C') $d_flags[] = 'NOT_CONVENIENT';\r
-\r
- // Get lists of breakfasts, lunches, dinners and snacks, ordered\r
- // randomly.\r
- if ($data->f['breakfast'] > 0) {\r
- $breakfasts = &$this->findMeals($data->f['breakfast'], 1, $b_flags);\r
- if (!$breakfasts) {\r
- $this->rollbackTransaction();\r
- return -3;\r
- }\r
- if ($breakfasts->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['breakfast']} cal breakfast for " . \r
- implode(',', $b_flags) . " flags.");\r
- }\r
- if ($data->f['lunch'] > 0) {\r
- $lunches = &$this->findMeals($data->f['lunch'], 2, $l_flags);\r
- if (!$lunches) {\r
- $this->rollbackTransaction();\r
- return -3;\r
- }\r
- if ($lunches->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['lunch']} cal lunch for " . \r
- implode(',', $l_flags) . " flags.");\r
- }\r
- if ($data->f['dinner'] > 0) {\r
- $dinners = &$this->findMeals($data->f['dinner'], 3, $d_flags);\r
- if (!$dinners) {\r
- $this->rollbackTransaction();\r
- return -3;\r
- }\r
- if ($dinners->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['dinner']} cal dinner for " . \r
- implode(',', $d_flags) . " flags.");\r
- }\r
- if ($data->f['snack'] > 0) {\r
- $snacks = &$this->findMeals($data->f['snack'], 4, $flags); \r
- if (!$snacks) {\r
- $this->rollbackTransaction();\r
- return -3;\r
- }\r
- if ($snacks->recordCount() == 0) reportError("User {$user_id} could not find a {$data->f['snack']} cal snack for " . \r
- implode(',', $flags) . " flags.");\r
- }\r
-\r
- // For each day, insert a breakfast, lunch, dinner and snack\r
- list($sy, $sm, $sd) = explode('-', $start_date);\r
- for ($i = 0; $i < $no_days; $i++) {\r
- $temp = array();\r
- $temp['user_id'] = $user_id;\r
- $temp['date'] = date('Y-m-d', mktime(0, 0, 0, $sm, $sd + $i, $sy));\r
- // Breakfast\r
- if ($data->f['breakfast'] > 0 && $breakfasts->recordCount() > 0) {\r
- $temp['breakfast_id'] = $breakfasts->f['meal_id'];\r
- $breakfasts->moveNext();\r
- if ($breakfasts->EOF) $breakfasts->moveFirst();\r
- }\r
- // Lunch\r
- if ($data->f['lunch'] > 0 && $lunches->recordCount() > 0) {\r
- $temp['lunch_id'] = $lunches->f['meal_id'];\r
- $lunches->moveNext();\r
- if ($lunches->EOF) $lunches->moveFirst();\r
- }\r
- // Dinner\r
- if ($data->f['dinner'] > 0 && $dinners->recordCount() > 0) {\r
- $temp['dinner_id'] = $dinners->f['meal_id'];\r
- $dinners->moveNext();\r
- if ($dinners->EOF) $dinners->moveFirst();\r
- }\r
- // Snack\r
- if ($data->f['snack'] > 0 && $snacks->recordCount() > 0) {\r
- $temp['snack_id'] = $snacks->f['meal_id'];\r
- $snacks->moveNext();\r
- if ($snacks->EOF) $snacks->moveFirst();\r
- }\r
-\r
- $status = $this->insert('users_mealplans', $temp);\r
- if ($status != 0) {\r
- $this->rollbackTransaction();\r
- return -4;\r
- }\r
- unset($temp);\r
- }\r
-\r
- // @@ Take care of overriding preferences\r
-\r
- return $this->endTransaction();\r
- }\r
-\r
- /**\r
- * Records a user's meal substitution to the database\r
- * @param $user_id The ID of the user to be updated\r
- * @param $date The date to update\r
- * @param $when_id The meal to replace\r
- * @param $meal_id The new meal to substitute\r
- * @return 0 success\r
- */\r
- function setUserMeal($user_id, $date, $when_id, $meal_id) {\r
- $fields = array('', 'breakfast_id', 'lunch_id', 'dinner_id', 'snack_id');\r
- return $this->update('users_mealplans',\r
- array($fields[$when_id] => $meal_id),\r
- array('user_id' => $user_id, 'date' => $date));\r
- }\r
-\r
- /**\r
- * Retrieves a user's shopping list\r
- * @param $user_id The ID fo the user to retrieve\r
- * @param $date The date from which to retrieve\r
- * @param $num_days The number of days from the date forward to retrieve\r
- */\r
- function &getShoppingList($user_id, $from, $to) {\r
- $this->clean($user_id);\r
- $this->clean($date);\r
-\r
- $sql = "\r
- SELECT description, food_id, name, measurement, base, type, name_pl, measurement_pl, qty, SUM(quantity) AS quantity FROM (\r
- (SELECT \r
- mcf.description, mf.food_id, mf.name, mf.measurement, mf.base, mf.type, mf.name_pl, mf.measurement_pl, mf.quantity AS qty, mfm.quantity AS quantity \r
- FROM \r
- medidiets_categories_foods mcf, medidiets_foods mf, medidiets_foods_map mfm, users_mealplans um \r
- WHERE \r
- mcf.category_id=mf.category_id\r
- AND mf.food_id=mfm.food_id \r
- AND mfm.meal_id IN (um.breakfast_id, um.lunch_id, um.dinner_id, um.snack_id)\r
- AND um.date BETWEEN '$from' AND '$to'\r
- AND user_id='$user_id')\r
- UNION ALL\r
- (SELECT \r
- mcf.description, mf.food_id, mf.name, mf.measurement, mf.base, mf.type, mf.name_pl, mf.measurement_pl, mf.quantity AS qty, mi.quantity AS quantity \r
- FROM \r
- medidiets_categories_foods mcf, medidiets_foods mf, medidiets_ingredients mi, medidiets_recipes_map mrm, users_mealplans um \r
- WHERE \r
- mcf.category_id=mf.category_id\r
- AND mf.food_id=mi.food_id \r
- AND mi.recipe_id=mrm.recipe_id \r
- AND mrm.meal_id IN (um.breakfast_id, um.lunch_id, um.dinner_id, um.snack_id) \r
- AND um.date BETWEEN '$from' AND '$to'\r
- AND user_id='$user_id')\r
- ) AS subselect\r
- GROUP BY description, food_id, name, measurement, base, type, name_pl, measurement_pl, qty\r
- ";\r
-\r
- return $this->selectSet($sql);\r
- }\r
-\r
- // Miscellaneous functions\r
-\r
- /*\r
- * Returns an array with the correct imperial or metric units\r
- * @return Array containing measurements\r
- */\r
- function getDefaultUnits() {\r
- global $defaultMeasurements;\r
-\r
- if ($defaultMeasurement == 'imperial') {\r
- $units = array('M' => 'oz', 'V' => 'fl.oz');\r
- }\r
- else {\r
- $units = array('M' => 'g', 'V' => 'mL');\r
- }\r
-\r
- return $units;\r
- }\r
-\r
- /*\r
- * A helper function to convert decimals to fractions\r
- * @param A decimal number to convert\r
- * @return The formatted version of the number\r
- */\r
- function _fracConvert($num) {\r
- $decpart = $num - floor($num);\r
-\r
- switch ($decpart * 4) {\r
- case 0:\r
- return number_format($num, 0);\r
- break;\r
- case 1:\r
- if (floor($num) != 0)\r
- return number_format(floor($num), 0) . ' 1/4';\r
- else\r
- return '1/4';\r
- break;\r
- case 2:\r
- if (floor($num) != 0)\r
- return number_format(floor($num), 0) . ' 1/2';\r
- else\r
- return '1/2';\r
- break;\r
- case 3:\r
- if (floor($num) != 0)\r
- return number_format(floor($num), 0) . ' 3/4';\r
- else\r
- return '3/4';\r
- break;\r
- default:\r
- if ($decpart == 0.33) {\r
- if (floor($num) != 0)\r
- return number_format(floor($num), 0) . ' 1/3';\r
- else\r
- return '1/3';\r
- }\r
- elseif ($decpart == 0.66 || $decpart == 0.67) {\r
- if (floor($num) != 0)\r
- return number_format(floor($num), 0) . ' 2/3';\r
- else\r
- return '2/3';\r
- }\r
- else return number_format($num, 2);\r
-\r
- break;\r
- }\r
- }\r
-\r
- /**\r
- * Return the string to be used to as the display for the ingredient\r
- *\r
- * The string is to be formatted depending upon the values of the measurement\r
- * and base variables. The string will also use the $defaultMeasurement\r
- * specified in the network config files.\r
- *\r
- * @param $name The name of the food of the ingredient\r
- * @param $name The pluralised form of the name\r
- * @param $quantity The amount of ingredient\r
- * @param $measurement The measurement of the food of the ingredient ('' if none)\r
- * @param $measurement The pluralised form of the measurement ('' if none)\r
- * @param $base The base size of the food of the ingredient ('' if none)\r
- * @param $type The base type of the food of the ingredient ('M' - mass, 'V' - volume)\r
- * @param $show_qty (optional) If false, only gives the name, not the quantity\r
- * @param $how How the ingredient is prepared.\r
- *\r
- */\r
- function getIngredientDisplay($name, $name_pl, $quantity, $measurement, $measurement_pl, $base, $type, $how, $show_qty = true) {\r
- global $defaultMeasurement;\r
-\r
- // set display units depending on defaultMeasurement\r
- $units = $this->getDefaultUnits();\r
-\r
- // if quantity is an integer value show only the integer\r
- if ($quantity == (int)$quantity) $quantity = (int)$quantity;\r
-\r
- // discard fractional part of base size, cos who can measure half a gram?\r
- if ($base != '') {\r
- $base = round($base);\r
- if ($base == 0) $base = 1;\r
- }\r
-\r
- if ($measurement != '' && $base != '') {\r
- // both measurement and base are set\r
- // eg. "2 1/2 375mL cans of Tomato Soup"\r
- $display_qty = $this->_fracConvert($quantity) . ' ';\r
- $display_nam = $base . $units[$type] . ' ';\r
- $display_nam .= ($quantity > 1) ? $measurement_pl : $measurement;\r
- $display_nam .= ' of ' . $name;\r
- }\r
- elseif ($measurement != '') {\r
- // measurement is set but base is not\r
- // eg. "4 2/3 slices of Bread"\r
- $display_qty = $this->_fracConvert($quantity) . ' ';\r
- $display_nam = ($quantity > 1) ? $measurement_pl : $measurement;\r
- $display_nam .= ' of ' . $name;\r
- }\r
- elseif ($base != '') {\r
- // base is set but measurement is not\r
- // eg. "500g of Beef"\r
- $display_qty = ceil($quantity * $base);\r
- $display_nam = $units[$type] . ' of ' . $name;\r
- }\r
- else {\r
- // neither measurement nor base is set\r
- // eg. "1 1/2 Apples"\r
- $display_qty = $this->_fracConvert($quantity) . ' ';\r
- $display_nam = ($quantity > 1) ? $name_pl : $name;\r
- }\r
- // Add 'crumbed', etc.\r
- if ($how != '') $display_nam .= ", {$how}";\r
-\r
- if ($show_qty)\r
- return $display_qty . $display_nam;\r
- else\r
- return $display_nam;\r
-\r
- }\r
-\r
- // Meal Manipulation Functions\r
-\r
- /**\r
- * Retrieve the Nutritional Data for a Food associated with a given meal\r
- * @param $meal_id The ID of the meal\r
- * @param $food_id The ID of the food\r
- * @return The set of nutritional data and food information\r
- */\r
- function &getMealFood($meal_id, $food_id) {\r
- $this->clean($meal_id);\r
- $this->clean($food_id);\r
- $sql = "SELECT f.*, fm.* FROM medidiets_foods_map fm, medidiets_foods f WHERE fm.food_id = f.food_id AND fm.meal_id = '{$meal_id}' AND fm.food_id = '{$food_id}'";\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /**\r
- * Retrieves all categories in the database, with all fields, sorted\r
- * alphabetically. This userland function excludes all categories with id's\r
- * less than zero!\r
- * @return A recordset\r
- */\r
- function &getRecipeCategories() {\r
- $sql = "SELECT * FROM medidiets_categories_rec WHERE category_id >= 0 ORDER BY description";\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /**\r
- * Retrieve the Nutritional Data for a Food associated with a given recipe\r
- * @param $recipe_id The ID of the recipe\r
- * @param $food_id The ID of the food\r
- * @return The set of nutritional data and food information\r
- */\r
- function &getRecipeIngredient($recipe_id, $food_id) {\r
- $this->clean($recipe_id);\r
- $this->clean($food_id);\r
- $sql = "SELECT f.*, fm.* FROM medidiets_ingredients fm, medidiets_foods f WHERE fm.food_id = f.food_id AND fm.recipe_id = '{$recipe_id}' AND fm.food_id = '{$food_id}'";\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /**\r
- * Retrieve a particular recipe\r
- * @param $recipe_id The ID of the recipe to retrieve\r
- * @return a recordset\r
- */\r
- function &getRecipe($recipe_id) {\r
- $this->clean($recipe_id);\r
- $sql = "SELECT * FROM medidiets_recipes WHERE recipe_id='{$recipe_id}'";\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /**\r
- * Retrieve all recipes in a particular category, sorted alphabetically\r
- * This userland version of the function doesn't show magic recipes.\r
- * @param $category_id The ID of the category in which to search\r
- * @param $data A boolean switch to retrieve the nutritional data for the recipe (default false)\r
- * @return a recordset\r
- */\r
- function &getRecipes($category_id, $data = false) {\r
- $this->clean($category_id);\r
- if ($data) {\r
- $sql = "SELECT * FROM\r
- medidiets_recipes r LEFT JOIN\r
- (SELECT i.recipe_id,\r
- sum(i.quantity * f.calories) AS calories,\r
- sum(i.quantity * f.kilojoules) AS kilojoules,\r
- sum(i.quantity * f.protein) AS protein,\r
- sum(i.quantity * f.fat) AS fat,\r
- sum(i.quantity * f.saturated_fat) AS saturated_fat,\r
- sum(i.quantity * f.carbohydrate) AS carbohydrate,\r
- sum(i.quantity * f.sugar) AS sugar,\r
- sum(i.quantity * f.fiber) AS fiber,\r
- sum(i.quantity * f.cholesterol) AS cholesterol,\r
- sum(i.quantity * f.sodium) AS sodium,\r
- sum(i.quantity * f.potassium) AS potassium,\r
- sum(i.quantity * f.calcium) AS calcium,\r
- sum(i.quantity * f.iron) AS iron,\r
- sum(i.quantity * f.zinc) AS zinc\r
- FROM\r
- medidiets_ingredients i,\r
- medidiets_foods f\r
- WHERE i.food_id = f.food_id\r
- GROUP BY i.recipe_id\r
- ) AS sub\r
- ON r.recipe_id = sub.recipe_id\r
- AND r.category_id = '{$category_id}'\r
- AND r.recipe_id >= 0\r
- ORDER BY r.name";\r
- }\r
- else {\r
- $sql = "SELECT * FROM medidiets_recipes WHERE category_id='{$category_id}' AND recipe_id >= 0 ORDER BY name";\r
- }\r
-\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /**\r
- * Retrieve the nutritional data for the specified recipe\r
- * @param $recipe_id The ID of the recipe to retrieve\r
- * @return a recordset\r
- */\r
- function &getRecipeData($recipe_id) {\r
- $this->clean($recipe_id);\r
- $sql = "SELECT * FROM\r
- medidiets_recipes r LEFT JOIN\r
- (SELECT i.recipe_id,\r
- sum(i.quantity * f.calories) AS total_calories,\r
- sum(i.quantity * f.kilojoules) AS total_kilojoules,\r
- sum(i.quantity * f.protein) AS total_protein,\r
- sum(i.quantity * f.fat) AS total_fat,\r
- sum(i.quantity * f.saturated_fat) AS total_saturated_fat,\r
- sum(i.quantity * f.carbohydrate) AS total_carbohydrate,\r
- sum(i.quantity * f.sugar) AS total_sugar,\r
- sum(i.quantity * f.fiber) AS total_fiber,\r
- sum(i.quantity * f.cholesterol) AS total_cholesterol,\r
- sum(i.quantity * f.sodium) AS total_sodium,\r
- sum(i.quantity * f.potassium) AS total_potassium,\r
- sum(i.quantity * f.calcium) AS total_calcium,\r
- sum(i.quantity * f.iron) AS total_iron,\r
- sum(i.quantity * f.zinc) AS total_zinc\r
- FROM\r
- medidiets_ingredients i,\r
- medidiets_foods f\r
- WHERE i.food_id = f.food_id\r
- GROUP BY i.recipe_id\r
- ) AS sub\r
- ON r.recipe_id = sub.recipe_id\r
- WHERE r.recipe_id = '{$recipe_id}'";\r
- return $this->selectSet($sql);\r
- }\r
-\r
- /**\r
- * Retrieve all ingredients for a recipe, sorted by their oid\r
- * @param $recipe_id The ID of the recipe to which the ingredients are needed\r
- * @return a recordset\r
- */\r
- function &getRecipeIngredients($recipe_id) {\r
- $this->clean($recipe_id);\r
- // @@ i.quantity must be after the f.* in the select until f.quantity removed...\r
- $sql = "SELECT f.*, i.quantity, i.how FROM medidiets_foods f, medidiets_ingredients i\r
- WHERE f.food_id = i.food_id\r
- AND i.recipe_id = '{$recipe_id}'\r
- ORDER BY i.oid";\r
-\r
- return $this->selectSet($sql);\r
- }\r
-\r
-}\r
-\r
-?>
\ No newline at end of file