PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/catalog/googlecheckout/library/google_base_feed_builder.php

http://google-checkout-oscommerce.googlecode.com/
PHP | 361 lines | 176 code | 37 blank | 148 comment | 9 complexity | b0d3683039b0cda8d415755ce38f84ba MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. Copyright (C) 2008 Google Inc.
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. */
  16. /**
  17. * Google Checkout v1.5.0
  18. * $Id: google_base_feed_builder.php 224 2009-03-11 16:31:28Z ed.davisson $
  19. *
  20. * Generates a feed (RSS 2.0) compatible with Google Base for products.
  21. *
  22. * See http://base.google.com/support/bin/answer.py?answer=73932
  23. *
  24. * osCommerce MySQL tables of interest:
  25. * categories
  26. * categories_description
  27. * products
  28. * products_descriptions
  29. * products_to_categories
  30. * manufacturers
  31. *
  32. * Mapping of XML elements to table->columns:
  33. *
  34. * Required:
  35. * description: products_description->products_description
  36. * id: products->products_id
  37. * link: products_description->products_url
  38. * price: products->products_price
  39. * title: products_description->products_name
  40. *
  41. * Recommended:
  42. * brand: manufacturers->manufacturers_name
  43. * condition: (not supported)
  44. * image_link: products->products_image
  45. * isbn: (not supported)
  46. * mpn: (not supported)
  47. * upc: (not supported)
  48. * weight: products->products_weight
  49. *
  50. * Optional:
  51. * color:
  52. * expiration_date
  53. * height: (not supported)
  54. * length: (not supported)
  55. * model_number: products->products_model
  56. * payment_accepted: TODO(eddavisson)
  57. * payment_notes: TODO(eddavisson)
  58. * price_type: (not supported)
  59. * product_type: categories_description->categories_name (calculated recursively)
  60. * quantity: products->products_quantity
  61. * shipping: TODO(eddavisson)
  62. * size: (not supported)
  63. * tax: TODO(eddavisson)
  64. * width: (not supported)
  65. * year: (not supported)
  66. *
  67. * TODO(eddavisson): How many more of these fields can we include?
  68. *
  69. * @author Ed Davisson (ed.davisson@gmail.com)
  70. */
  71. require_once(DIR_FS_CATALOG . 'googlecheckout/library/xml/google_xml_builder.php');
  72. class GoogleBaseFeedBuilder {
  73. var $xml;
  74. var $languages_id;
  75. var $categories_tree;
  76. /**
  77. * Constructor.
  78. */
  79. function GoogleBaseFeedBuilder($languages_id) {
  80. $this->xml = new GoogleXmlBuilder();
  81. $this->languages_id = $languages_id;
  82. $this->categories_tree = $this->build_categories_tree();
  83. }
  84. /**
  85. * Adds all information needed to create a Google Base feed (RSS 2.0).
  86. */
  87. function get_xml() {
  88. $this->xml->Push("rss", array("version" => "2.0",
  89. "xmlns:g" => "http://base.google.com/ns/1.0"));
  90. $this->xml->Push("channel");
  91. $this->add_feed_info();
  92. $this->add_items();
  93. $this->xml->Pop("channel");
  94. $this->xml->Pop("rss");
  95. return $this->xml->GetXml();
  96. }
  97. /**
  98. * Adds feed info (title, link, description) to the XML.
  99. */
  100. function add_feed_info() {
  101. $title_query = tep_db_query(
  102. "select configuration_value "
  103. . "from configuration "
  104. . "where configuration_key = \"STORE_NAME\"");
  105. $row = tep_db_fetch_array($title_query);
  106. $title = $row['configuration_value'];
  107. $this->xml->Element('title', $title);
  108. $this->xml->Element('link', HTTP_SERVER . DIR_WS_HTTP_CATALOG);
  109. // osCommerce doesn't store a description of the store.
  110. $this->xml->Element('description', $title);
  111. }
  112. /**
  113. * Adds items (products) to the XML.
  114. */
  115. function add_items() {
  116. $products_query = $this->get_products_query();
  117. while ($product = tep_db_fetch_array($products_query)) {
  118. $this->add_item($product);
  119. }
  120. }
  121. /**
  122. * Adds a single item (product) to the XML.
  123. */
  124. function add_item($product) {
  125. $this->xml->Push('item');
  126. // Required, global namespace.
  127. $this->add_title($product);
  128. $this->add_link($product);
  129. $this->add_description($product);
  130. // Required, Google namespace.
  131. $this->add_brand($product);
  132. $this->add_id($product);
  133. $this->add_price($product);
  134. // Optional.
  135. $this->add_image_link($product);
  136. $this->add_weight($product);
  137. $this->add_model_number($product);
  138. $this->add_payment_notes($product);
  139. $this->add_product_type($product);
  140. $this->add_quantity($product);
  141. $this->xml->Pop('item');
  142. }
  143. /**
  144. * Builds the categories tree.
  145. */
  146. function build_categories_tree() {
  147. $categories_tree = array();
  148. $categories_query = $this->get_categories_query();
  149. while ($category = tep_db_fetch_array($categories_query)) {
  150. $categories_tree[$category['categories_id']] = array(
  151. 'name' => $category['categories_name'],
  152. 'parent_id' => $category['parent_id']);
  153. }
  154. return $categories_tree;
  155. }
  156. /**
  157. * Returns a query containing the information necessary
  158. * to build the categories tree.
  159. */
  160. function get_categories_query() {
  161. return tep_db_query(
  162. "select c.categories_id, "
  163. . "c.parent_id, "
  164. . "cd.categories_name "
  165. . "from " . TABLE_CATEGORIES . " c, "
  166. . TABLE_CATEGORIES_DESCRIPTION . " cd "
  167. . "where c.categories_id = cd.categories_id "
  168. . "and cd.language_id = " . (int) $this->languages_id . " ");
  169. }
  170. /**
  171. * Traverses the categories tree to construct an array of the
  172. * categories containing the provided category_id.
  173. */
  174. function create_category_array($category_id, &$array) {
  175. $name = $this->categories_tree[$category_id]['name'];
  176. array_push($array, $name);
  177. $parent_id = $this->categories_tree[$category_id]['parent_id'];
  178. if ($parent_id == 0) {
  179. $array = array_reverse($array);
  180. return;
  181. } else {
  182. $this->create_category_array($parent_id, $array);
  183. }
  184. }
  185. /**
  186. * Returns a query over all products containing the columns
  187. * needed to generate the field.
  188. */
  189. function get_products_query() {
  190. return tep_db_query(
  191. "select p.products_id, "
  192. . "p.products_price, "
  193. . "p.products_image, "
  194. . "p.products_weight, "
  195. . "p.products_model, "
  196. . "p.products_quantity, "
  197. . "pd.products_id, "
  198. . "pd.products_description, "
  199. . "pd.products_url, "
  200. . "pd.products_name, "
  201. . "m.manufacturers_name, "
  202. . "ptc.categories_id "
  203. . "from " . TABLE_PRODUCTS . " p, "
  204. . TABLE_PRODUCTS_DESCRIPTION . " pd, "
  205. . TABLE_MANUFACTURERS . " m, "
  206. . TABLE_PRODUCTS_TO_CATEGORIES . " ptc "
  207. . "where pd.products_id = p.products_id "
  208. . "and m.manufacturers_id = p.manufacturers_id "
  209. . "and ptc.products_id = p.products_id "
  210. . "and pd.language_id = " . (int) $this->languages_id . " ");
  211. }
  212. /**
  213. * Adds an element to the XML if content is non-empty.
  214. */
  215. function add_if_not_empty($element, $content) {
  216. if (!empty($content)) {
  217. $this->xml->Element($element, $content);
  218. }
  219. }
  220. /**
  221. * Adds the 'title' element.
  222. */
  223. function add_title($product) {
  224. $title = $product['products_name'];
  225. $this->add_if_not_empty('title', $title);
  226. }
  227. /**
  228. * Adds the 'link' element.
  229. */
  230. function add_link($product) {
  231. $link = tep_href_link(
  232. FILENAME_PRODUCT_INFO,
  233. 'products_id=' . $product['products_id']);
  234. $this->add_if_not_empty('link', $link);
  235. }
  236. /**
  237. * Adds the 'brand' element.
  238. */
  239. function add_brand($product) {
  240. $brand = $product['manufacturers_name'];
  241. $this->add_if_not_empty('g:brand', $brand);
  242. }
  243. /**
  244. * Adds the 'description' element.
  245. *
  246. * As of 1/13/09, HTML is only supported in individually
  247. * posted items.
  248. *
  249. * See http://base.google.com/support/bin/answer.py?answer=46116.
  250. */
  251. function add_description($product) {
  252. $description = strip_tags($product['products_description']);
  253. $this->add_if_not_empty('description', $description);
  254. }
  255. /**
  256. * Adds the 'id' element.
  257. */
  258. function add_id($product) {
  259. $id = $product['products_id'];
  260. $this->add_if_not_empty('g:id', $id);
  261. }
  262. /**
  263. * Adds the 'price' element.
  264. */
  265. function add_price($product) {
  266. $price = round($product['products_price'], 2);
  267. $this->add_if_not_empty('g:price', $price);
  268. }
  269. /**
  270. * Adds the 'image_link' element.
  271. */
  272. function add_image_link($product) {
  273. $image_link = HTTP_SERVER . DIR_WS_HTTP_CATALOG
  274. . DIR_WS_IMAGES . $product['products_image'];
  275. $this->add_if_not_empty('g:image_link', $image_link);
  276. }
  277. /**
  278. * Adds the 'weight' element.
  279. */
  280. function add_weight($product) {
  281. $weight = $product['products_weight'];
  282. $this->add_if_not_empty('g:weight', $weight);
  283. }
  284. /**
  285. * Adds the 'model_number' element.
  286. */
  287. function add_model_number($product) {
  288. $model_number = $product['products_model'];
  289. $this->add_if_not_empty('g:model_number', $model_number);
  290. }
  291. /**
  292. * Adds the 'payment_notes' element.
  293. */
  294. function add_payment_notes($product) {
  295. // TODO(eddavisson): What should we actually say here?
  296. $payment_notes = "Google Checkout";
  297. $this->add_if_not_empty('g:payment_notes', $payment_notes);
  298. }
  299. function add_product_type($product) {
  300. $category_id = $product['categories_id'];
  301. $category_array = array();
  302. $this->create_category_array($category_id, $category_array);
  303. $product_type = "";
  304. $length = count($category_array);
  305. for ($i = 0; $i < $length; $i++) {
  306. $product_type .= $category_array[$i];
  307. if ($i != $length - 1) {
  308. $product_type .= " > ";
  309. }
  310. }
  311. $this->add_if_not_empty('g:product_type', $product_type);
  312. }
  313. /**
  314. * Adds the 'quantity' element.
  315. */
  316. function add_quantity($product) {
  317. $quantity = $product['products_quantity'];
  318. $this->add_if_not_empty('g:quantity', $quantity);
  319. }
  320. }
  321. ?>