diff --git a/api/Blog.php b/api/Blog.php index d29af50..a363ad7 100755 --- a/api/Blog.php +++ b/api/Blog.php @@ -14,68 +14,74 @@ class Blog extends Simpla { - /* - * - * Функция возвращает пост по его id или url - * (в зависимости от типа аргумента, int - id, string - url) - * @param $id id или url поста - * - */ - public function get_post($id) - { - if(is_int($id)) - $where = $this->db->placehold(' WHERE b.id=? ', intval($id)); - else - $where = $this->db->placehold(' WHERE b.url=? ', $id); - - $query = $this->db->placehold("SELECT b.id, b.url, b.name, b.annotation, b.text, b.meta_title, b.meta_keywords, b.meta_description, b.visible, b.date + /* + * + * Функция возвращает пост по его id или url + * (в зависимости от типа аргумента, int - id, string - url) + * @param $id id или url поста + * + */ + public function get_post($id) + { + if (is_int($id)) { + $where = $this->db->placehold(' WHERE b.id=? ', intval($id)); + } else { + $where = $this->db->placehold(' WHERE b.url=? ', $id); + } + + $query = $this->db->placehold("SELECT b.id, b.url, b.name, b.annotation, b.text, b.meta_title, b.meta_keywords, b.meta_description, b.visible, b.date FROM __blog b $where LIMIT 1"); - if($this->db->query($query)) - return $this->db->result(); - else - return false; - } - - /* - * - * Функция возвращает массив постов, удовлетворяющих фильтру - * @param $filter - * - */ - public function get_posts($filter = array()) - { - // По умолчанию - $limit = 1000; - $page = 1; - $post_id_filter = ''; - $visible_filter = ''; - $keyword_filter = ''; - $posts = array(); - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - if(!empty($filter['id'])) - $post_id_filter = $this->db->placehold('AND b.id in(?@)', (array)$filter['id']); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('AND b.visible = ?', intval($filter['visible'])); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); - } - - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - - $query = $this->db->placehold("SELECT b.id, b.url, b.name, b.annotation, b.text, b.meta_title, b.meta_keywords, b.meta_description, b.visible, b.date + if ($this->db->query($query)) { + return $this->db->result(); + } else { + return false; + } + } + + /* + * + * Функция возвращает массив постов, удовлетворяющих фильтру + * @param $filter + * + */ + public function get_posts($filter = array()) + { + // По умолчанию + $limit = 1000; + $page = 1; + $post_id_filter = ''; + $visible_filter = ''; + $keyword_filter = ''; + $posts = array(); + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + if (!empty($filter['id'])) { + $post_id_filter = $this->db->placehold('AND b.id in(?@)', (array)$filter['id']); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('AND b.visible = ?', intval($filter['visible'])); + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); + } + } + + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + + $query = $this->db->placehold("SELECT b.id, b.url, b.name, b.annotation, b.text, b.meta_title, b.meta_keywords, b.meta_description, b.visible, b.date FROM __blog b WHERE 1 $post_id_filter @@ -84,148 +90,154 @@ public function get_posts($filter = array()) ORDER BY date DESC, id DESC $sql_limit"); - $this->db->query($query); - return $this->db->results(); - } - - - /* - * - * Функция вычисляет количество постов, удовлетворяющих фильтру - * @param $filter - * - */ - public function count_posts($filter = array()) - { - $post_id_filter = ''; - $visible_filter = ''; - $keyword_filter = ''; - - if(!empty($filter['id'])) - $post_id_filter = $this->db->placehold('AND b.id in(?@)', (array)$filter['id']); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('AND b.visible = ?', intval($filter['visible'])); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); - } - - $query = $this->db->placehold("SELECT COUNT(distinct b.id) as count + $this->db->query($query); + return $this->db->results(); + } + + + /* + * + * Функция вычисляет количество постов, удовлетворяющих фильтру + * @param $filter + * + */ + public function count_posts($filter = array()) + { + $post_id_filter = ''; + $visible_filter = ''; + $keyword_filter = ''; + + if (!empty($filter['id'])) { + $post_id_filter = $this->db->placehold('AND b.id in(?@)', (array)$filter['id']); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('AND b.visible = ?', intval($filter['visible'])); + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); + } + } + + $query = $this->db->placehold("SELECT COUNT(distinct b.id) as count FROM __blog b WHERE 1 $post_id_filter $visible_filter $keyword_filter"); - if($this->db->query($query)) - return $this->db->result('count'); - else - return false; - } - - /* - * - * Создание поста - * @param $post - * - */ - public function add_post($post) - { - if(!isset($post->date)) - $date_query = ', date=NOW()'; - else - $date_query = ''; - - $query = $this->db->placehold("INSERT INTO __blog SET ?% $date_query", $post); - - if(!$this->db->query($query)) - return false; - else - return $this->db->insert_id(); - } - - - /* - * - * Обновить пост(ы) - * @param $post - * - */ - public function update_post($id, $post) - { - $query = $this->db->placehold("UPDATE __blog SET ?% WHERE id in(?@) LIMIT ?", $post, (array)$id, count((array)$id)); - $this->db->query($query); - return $id; - } - - - /* - * - * Удалить пост - * @param $id - * - */ - public function delete_post($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __blog WHERE id=? LIMIT 1", intval($id)); - if($this->db->query($query)) - { - $query = $this->db->placehold("DELETE FROM __comments WHERE type='blog' AND object_id=?", intval($id)); - if($this->db->query($query)) - return true; - } - } - return false; - } - - - /* - * - * Следующий пост - * @param $post - * - */ - public function get_next_post($id) - { - $this->db->query("SELECT date FROM __blog WHERE id=? LIMIT 1", $id); - $date = $this->db->result('date'); - - $this->db->query("(SELECT id FROM __blog WHERE date=? AND id>? AND visible ORDER BY id limit 1) + if ($this->db->query($query)) { + return $this->db->result('count'); + } else { + return false; + } + } + + /* + * + * Создание поста + * @param $post + * + */ + public function add_post($post) + { + if (!isset($post->date)) { + $date_query = ', date=NOW()'; + } else { + $date_query = ''; + } + + $query = $this->db->placehold("INSERT INTO __blog SET ?% $date_query", $post); + + if (!$this->db->query($query)) { + return false; + } else { + return $this->db->insert_id(); + } + } + + + /* + * + * Обновить пост(ы) + * @param $post + * + */ + public function update_post($id, $post) + { + $query = $this->db->placehold("UPDATE __blog SET ?% WHERE id in(?@) LIMIT ?", $post, (array)$id, count((array)$id)); + $this->db->query($query); + return $id; + } + + + /* + * + * Удалить пост + * @param $id + * + */ + public function delete_post($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __blog WHERE id=? LIMIT 1", intval($id)); + if ($this->db->query($query)) { + $query = $this->db->placehold("DELETE FROM __comments WHERE type='blog' AND object_id=?", intval($id)); + if ($this->db->query($query)) { + return true; + } + } + } + return false; + } + + + /* + * + * Следующий пост + * @param $post + * + */ + public function get_next_post($id) + { + $this->db->query("SELECT date FROM __blog WHERE id=? LIMIT 1", $id); + $date = $this->db->result('date'); + + $this->db->query("(SELECT id FROM __blog WHERE date=? AND id>? AND visible ORDER BY id limit 1) UNION (SELECT id FROM __blog WHERE date>? AND visible ORDER BY date, id limit 1)", - $date, $id, $date); - $next_id = $this->db->result('id'); - if($next_id) - return $this->get_post(intval($next_id)); - else - return false; - } - - /* - * - * Предыдущий пост - * @param $post - * - */ - public function get_prev_post($id) - { - $this->db->query("SELECT date FROM __blog WHERE id=? LIMIT 1", $id); - $date = $this->db->result('date'); - - $this->db->query("(SELECT id FROM __blog WHERE date=? AND iddb->result('id'); + if ($next_id) { + return $this->get_post(intval($next_id)); + } else { + return false; + } + } + + /* + * + * Предыдущий пост + * @param $post + * + */ + public function get_prev_post($id) + { + $this->db->query("SELECT date FROM __blog WHERE id=? LIMIT 1", $id); + $date = $this->db->result('date'); + + $this->db->query("(SELECT id FROM __blog WHERE date=? AND iddb->result('id'); - if($prev_id) - return $this->get_post(intval($prev_id)); - else - return false; - } + $date, $id, $date); + $prev_id = $this->db->result('id'); + if ($prev_id) { + return $this->get_post(intval($prev_id)); + } else { + return false; + } + } } diff --git a/api/Brands.php b/api/Brands.php index ddf78ae..67743d1 100755 --- a/api/Brands.php +++ b/api/Brands.php @@ -13,133 +13,131 @@ class Brands extends Simpla { - /* - * - * Функция возвращает массив брендов, удовлетворяющих фильтру - * @param $filter - * - */ - public function get_brands($filter = array()) - { - - $category_id_filter = ''; - $visible_filter = ''; - $in_stock_filter = ''; - - if(isset($filter['in_stock'])) - $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('AND p.visible=?', intval($filter['visible'])); - - if(!empty($filter['category_id'])) - $category_id_filter = $this->db->placehold("LEFT JOIN __products p ON p.brand_id=b.id LEFT JOIN __products_categories pc ON p.id = pc.product_id WHERE pc.category_id in(?@) $visible_filter $in_stock_filter", (array)$filter['category_id']); - - // Выбираем все бренды - $query = $this->db->placehold("SELECT DISTINCT b.id, b.name, b.url, b.meta_title, b.meta_keywords, b.meta_description, b.description, b.image + /* + * + * Функция возвращает массив брендов, удовлетворяющих фильтру + * @param $filter + * + */ + public function get_brands($filter = array()) + { + $category_id_filter = ''; + $visible_filter = ''; + $in_stock_filter = ''; + + if (isset($filter['in_stock'])) { + $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('AND p.visible=?', intval($filter['visible'])); + } + + if (!empty($filter['category_id'])) { + $category_id_filter = $this->db->placehold("LEFT JOIN __products p ON p.brand_id=b.id LEFT JOIN __products_categories pc ON p.id = pc.product_id WHERE pc.category_id in(?@) $visible_filter $in_stock_filter", (array)$filter['category_id']); + } + + // Выбираем все бренды + $query = $this->db->placehold("SELECT DISTINCT b.id, b.name, b.url, b.meta_title, b.meta_keywords, b.meta_description, b.description, b.image FROM __brands b $category_id_filter ORDER BY b.name"); - $this->db->query($query); - - return $this->db->results(); - } - - /* - * - * Функция возвращает бренд по его id или url - * (в зависимости от типа аргумента, int - id, string - url) - * @param $id id или url поста - * - */ - public function get_brand($id) - { - if(is_int($id)) - $filter = $this->db->placehold('b.id = ?', $id); - else - $filter = $this->db->placehold('b.url = ?', $id); - - $query = $this->db->placehold("SELECT b.id, b.name, b.url, b.meta_title, b.meta_keywords, b.meta_description, b.description, b.image + $this->db->query($query); + + return $this->db->results(); + } + + /* + * + * Функция возвращает бренд по его id или url + * (в зависимости от типа аргумента, int - id, string - url) + * @param $id id или url поста + * + */ + public function get_brand($id) + { + if (is_int($id)) { + $filter = $this->db->placehold('b.id = ?', $id); + } else { + $filter = $this->db->placehold('b.url = ?', $id); + } + + $query = $this->db->placehold("SELECT b.id, b.name, b.url, b.meta_title, b.meta_keywords, b.meta_description, b.description, b.image FROM __brands b WHERE $filter LIMIT 1"); - $this->db->query($query); - return $this->db->result(); - } - - /* - * - * Добавление бренда - * @param $brand - * - */ - public function add_brand($brand) - { - $brand = (array)$brand; - if(empty($brand['url'])) - { - $brand['url'] = preg_replace("/[\s]+/ui", '_', $brand['name']); - $brand['url'] = strtolower(preg_replace("/[^0-9a-zа-я_]+/ui", '', $brand['url'])); - } - - $this->db->query("INSERT INTO __brands SET ?%", $brand); - return $this->db->insert_id(); - } - - /* - * - * Обновление бренда(ов) - * @param $brand - * - */ - public function update_brand($id, $brand) - { - $query = $this->db->placehold("UPDATE __brands SET ?% WHERE id=? LIMIT 1", $brand, intval($id)); - $this->db->query($query); - return $id; - } - - /* - * - * Удаление бренда - * @param $id - * - */ - public function delete_brand($id) - { - if(!empty($id)) - { - $this->delete_image($id); - $query = $this->db->placehold("DELETE FROM __brands WHERE id=? LIMIT 1", $id); - $this->db->query($query); - $query = $this->db->placehold("UPDATE __products SET brand_id=NULL WHERE brand_id=?", $id); - $this->db->query($query); - } - } - - /* - * - * Удаление изображения бренда - * @param $id - * - */ - public function delete_image($brand_id) - { - $query = $this->db->placehold("SELECT image FROM __brands WHERE id=?", intval($brand_id)); - $this->db->query($query); - $filename = $this->db->result('image'); - if(!empty($filename)) - { - $query = $this->db->placehold("UPDATE __brands SET image=NULL WHERE id=?", $brand_id); - $this->db->query($query); - $query = $this->db->placehold("SELECT count(*) as count FROM __brands WHERE image=? LIMIT 1", $filename); - $this->db->query($query); - $count = $this->db->result('count'); - if($count == 0) - { - @unlink($this->config->root_dir.$this->config->brands_images_dir.$filename); - } - } - } - + $this->db->query($query); + return $this->db->result(); + } + + /* + * + * Добавление бренда + * @param $brand + * + */ + public function add_brand($brand) + { + $brand = (array)$brand; + if (empty($brand['url'])) { + $brand['url'] = preg_replace("/[\s]+/ui", '_', $brand['name']); + $brand['url'] = strtolower(preg_replace("/[^0-9a-zа-я_]+/ui", '', $brand['url'])); + } + + $this->db->query("INSERT INTO __brands SET ?%", $brand); + return $this->db->insert_id(); + } + + /* + * + * Обновление бренда(ов) + * @param $brand + * + */ + public function update_brand($id, $brand) + { + $query = $this->db->placehold("UPDATE __brands SET ?% WHERE id=? LIMIT 1", $brand, intval($id)); + $this->db->query($query); + return $id; + } + + /* + * + * Удаление бренда + * @param $id + * + */ + public function delete_brand($id) + { + if (!empty($id)) { + $this->delete_image($id); + $query = $this->db->placehold("DELETE FROM __brands WHERE id=? LIMIT 1", $id); + $this->db->query($query); + $query = $this->db->placehold("UPDATE __products SET brand_id=NULL WHERE brand_id=?", $id); + $this->db->query($query); + } + } + + /* + * + * Удаление изображения бренда + * @param $id + * + */ + public function delete_image($brand_id) + { + $query = $this->db->placehold("SELECT image FROM __brands WHERE id=?", intval($brand_id)); + $this->db->query($query); + $filename = $this->db->result('image'); + if (!empty($filename)) { + $query = $this->db->placehold("UPDATE __brands SET image=NULL WHERE id=?", $brand_id); + $this->db->query($query); + $query = $this->db->placehold("SELECT count(*) as count FROM __brands WHERE image=? LIMIT 1", $filename); + $this->db->query($query); + $count = $this->db->result('count'); + if ($count == 0) { + @unlink($this->config->root_dir.$this->config->brands_images_dir.$filename); + } + } + } } diff --git a/api/Cart.php b/api/Cart.php index d715b3a..ee5bb5a 100755 --- a/api/Cart.php +++ b/api/Cart.php @@ -14,185 +14,169 @@ class Cart extends Simpla { - /* - * - * Функция возвращает корзину - * - */ - public function get_cart() - { - $cart = new stdClass(); - $cart->purchases = array(); - $cart->total_price = 0; - $cart->total_products = 0; - $cart->coupon = null; - $cart->discount = 0; - $cart->coupon_discount = 0; - - // Берем из сессии список variant_id=>amount - if(!empty($_SESSION['shopping_cart'])) - { - $session_items = $_SESSION['shopping_cart']; - - $variants = $this->variants->get_variants(array('id'=>array_keys($session_items))); - if(!empty($variants)) - { - - foreach($variants as $variant) - { - $items[$variant->id] = new stdClass(); - $items[$variant->id]->variant = $variant; - $items[$variant->id]->amount = $session_items[$variant->id]; - $products_ids[] = $variant->product_id; - } - - $products = array(); - foreach($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) - $products[$p->id]=$p; - - $images = $this->products->get_images(array('product_id'=>$products_ids)); - foreach($images as $image) - $products[$image->product_id]->images[$image->id] = $image; - - - foreach($items as $variant_id=>$item) - { - $purchase = null; - if(!empty($products[$item->variant->product_id])) - { - $purchase = new stdClass(); - $purchase->product = $products[$item->variant->product_id]; - $purchase->variant = $item->variant; - $purchase->amount = $item->amount; - - $cart->purchases[] = $purchase; - $cart->total_price += $item->variant->price*$item->amount; - $cart->total_products += $item->amount; - } - } - - // Пользовательская скидка - $cart->discount = 0; - if(isset($_SESSION['user_id']) && $user = $this->users->get_user(intval($_SESSION['user_id']))) - $cart->discount = $user->discount; - - $cart->total_price *= (100-$cart->discount)/100; - - // Скидка по купону - if(isset($_SESSION['coupon_code'])) - { - $cart->coupon = $this->coupons->get_coupon($_SESSION['coupon_code']); - if($cart->coupon && $cart->coupon->valid && $cart->total_price>=$cart->coupon->min_order_price) - { - if($cart->coupon->type=='absolute') - { - // Абсолютная скидка не более суммы заказа - $cart->coupon_discount = $cart->total_price>$cart->coupon->value?$cart->coupon->value:$cart->total_price; - $cart->total_price = max(0, $cart->total_price-$cart->coupon->value); - } - else - { - $cart->coupon_discount = $cart->total_price * ($cart->coupon->value)/100; - $cart->total_price = $cart->total_price-$cart->coupon_discount; - } - } - else - { - unset($_SESSION['coupon_code']); - } - } - - } - } - - return $cart; - } - - /* - * - * Добавление варианта товара в корзину - * - */ - public function add_item($variant_id, $amount = 1) - { - $amount = max(1, $amount); - - if(isset($_SESSION['shopping_cart'][$variant_id])) - $amount = max(1, $amount+$_SESSION['shopping_cart'][$variant_id]); - - // Выберем товар из базы, заодно убедившись в его существовании - $variant = $this->variants->get_variant($variant_id); - - // Если товар существует, добавим его в корзину - if(!empty($variant) && ($variant->stock>0) ) - { - // Не дадим больше чем на складе - $amount = min($amount, $variant->stock); - - $_SESSION['shopping_cart'][$variant_id] = intval($amount); - } - } - - /* - * - * Обновление количества товара - * - */ - public function update_item($variant_id, $amount = 1) - { - $amount = max(1, $amount); - - // Выберем товар из базы, заодно убедившись в его существовании - $variant = $this->variants->get_variant($variant_id); - - // Если товар существует, добавим его в корзину - if(!empty($variant) && $variant->stock>0) - { - // Не дадим больше чем на складе - $amount = min($amount, $variant->stock); - - $_SESSION['shopping_cart'][$variant_id] = intval($amount); - } - - } - - - /* - * - * Удаление товара из корзины - * - */ - public function delete_item($variant_id) - { - unset($_SESSION['shopping_cart'][$variant_id]); - } - - /* - * - * Очистка корзины - * - */ - public function empty_cart() - { - unset($_SESSION['shopping_cart']); - unset($_SESSION['coupon_code']); - } - - /* - * - * Применить купон - * - */ - public function apply_coupon($coupon_code) - { - $coupon = $this->coupons->get_coupon((string)$coupon_code); - if($coupon && $coupon->valid) - { - $_SESSION['coupon_code'] = $coupon->code; - } - else - { - unset($_SESSION['coupon_code']); - } - } + /* + * + * Функция возвращает корзину + * + */ + public function get_cart() + { + $cart = new stdClass(); + $cart->purchases = array(); + $cart->total_price = 0; + $cart->total_products = 0; + $cart->coupon = null; + $cart->discount = 0; + $cart->coupon_discount = 0; + + // Берем из сессии список variant_id=>amount + if (!empty($_SESSION['shopping_cart'])) { + $session_items = $_SESSION['shopping_cart']; + + $variants = $this->variants->get_variants(array('id'=>array_keys($session_items))); + if (!empty($variants)) { + foreach ($variants as $variant) { + $items[$variant->id] = new stdClass(); + $items[$variant->id]->variant = $variant; + $items[$variant->id]->amount = $session_items[$variant->id]; + $products_ids[] = $variant->product_id; + } + + $products = array(); + foreach ($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) { + $products[$p->id]=$p; + } + + $images = $this->products->get_images(array('product_id'=>$products_ids)); + foreach ($images as $image) { + $products[$image->product_id]->images[$image->id] = $image; + } + + + foreach ($items as $variant_id=>$item) { + $purchase = null; + if (!empty($products[$item->variant->product_id])) { + $purchase = new stdClass(); + $purchase->product = $products[$item->variant->product_id]; + $purchase->variant = $item->variant; + $purchase->amount = $item->amount; + + $cart->purchases[] = $purchase; + $cart->total_price += $item->variant->price*$item->amount; + $cart->total_products += $item->amount; + } + } + + // Пользовательская скидка + $cart->discount = 0; + if (isset($_SESSION['user_id']) && $user = $this->users->get_user(intval($_SESSION['user_id']))) { + $cart->discount = $user->discount; + } + + $cart->total_price *= (100-$cart->discount)/100; + + // Скидка по купону + if (isset($_SESSION['coupon_code'])) { + $cart->coupon = $this->coupons->get_coupon($_SESSION['coupon_code']); + if ($cart->coupon && $cart->coupon->valid && $cart->total_price>=$cart->coupon->min_order_price) { + if ($cart->coupon->type=='absolute') { + // Абсолютная скидка не более суммы заказа + $cart->coupon_discount = $cart->total_price>$cart->coupon->value?$cart->coupon->value:$cart->total_price; + $cart->total_price = max(0, $cart->total_price-$cart->coupon->value); + } else { + $cart->coupon_discount = $cart->total_price * ($cart->coupon->value)/100; + $cart->total_price = $cart->total_price-$cart->coupon_discount; + } + } else { + unset($_SESSION['coupon_code']); + } + } + } + } + + return $cart; + } + + /* + * + * Добавление варианта товара в корзину + * + */ + public function add_item($variant_id, $amount = 1) + { + $amount = max(1, $amount); + + if (isset($_SESSION['shopping_cart'][$variant_id])) { + $amount = max(1, $amount+$_SESSION['shopping_cart'][$variant_id]); + } + + // Выберем товар из базы, заодно убедившись в его существовании + $variant = $this->variants->get_variant($variant_id); + + // Если товар существует, добавим его в корзину + if (!empty($variant) && ($variant->stock>0)) { + // Не дадим больше чем на складе + $amount = min($amount, $variant->stock); + + $_SESSION['shopping_cart'][$variant_id] = intval($amount); + } + } + + /* + * + * Обновление количества товара + * + */ + public function update_item($variant_id, $amount = 1) + { + $amount = max(1, $amount); + + // Выберем товар из базы, заодно убедившись в его существовании + $variant = $this->variants->get_variant($variant_id); + + // Если товар существует, добавим его в корзину + if (!empty($variant) && $variant->stock>0) { + // Не дадим больше чем на складе + $amount = min($amount, $variant->stock); + + $_SESSION['shopping_cart'][$variant_id] = intval($amount); + } + } + + + /* + * + * Удаление товара из корзины + * + */ + public function delete_item($variant_id) + { + unset($_SESSION['shopping_cart'][$variant_id]); + } + + /* + * + * Очистка корзины + * + */ + public function empty_cart() + { + unset($_SESSION['shopping_cart']); + unset($_SESSION['coupon_code']); + } + + /* + * + * Применить купон + * + */ + public function apply_coupon($coupon_code) + { + $coupon = $this->coupons->get_coupon((string)$coupon_code); + if ($coupon && $coupon->valid) { + $_SESSION['coupon_code'] = $coupon->code; + } else { + unset($_SESSION['coupon_code']); + } + } } diff --git a/api/Categories.php b/api/Categories.php index eea3030..e48d12c 100755 --- a/api/Categories.php +++ b/api/Categories.php @@ -13,247 +13,247 @@ class Categories extends Simpla { - // Список указателей на категории в дереве категорий (ключ = id категории) - private $all_categories; - // Дерево категорий - private $categories_tree; - - // Функция возвращает массив категорий - public function get_categories($filter = array()) - { - if(!isset($this->categories_tree)) - $this->init_categories(); - - if(!empty($filter['product_id'])) - { - $query = $this->db->placehold("SELECT category_id FROM __products_categories WHERE product_id in(?@) ORDER BY position", (array)$filter['product_id']); - $this->db->query($query); - $categories_ids = $this->db->results('category_id'); - $result = array(); - foreach($categories_ids as $id) - if(isset($this->all_categories[$id])) - $result[$id] = $this->all_categories[$id]; - return $result; - } - - return $this->all_categories; - } - - // Функция возвращает id категорий для заданного товара - public function get_product_categories($product_id) - { - $query = $this->db->placehold("SELECT product_id, category_id, position FROM __products_categories WHERE product_id in(?@) ORDER BY position", (array)$product_id); - $this->db->query($query); - return $this->db->results(); - } - - // Функция возвращает id категорий для всех товаров - public function get_products_categories() - { - $query = $this->db->placehold("SELECT product_id, category_id, position FROM __products_categories ORDER BY position"); - $this->db->query($query); - return $this->db->results(); - } - - // Функция возвращает дерево категорий - public function get_categories_tree() - { - if(!isset($this->categories_tree)) - $this->init_categories(); - - return $this->categories_tree; - } - - // Функция возвращает заданную категорию - public function get_category($id) - { - if(!isset($this->all_categories)) - $this->init_categories(); - if(is_int($id) && array_key_exists(intval($id), $this->all_categories)) - return $category = $this->all_categories[intval($id)]; - elseif(is_string($id)) - foreach ($this->all_categories as $category) - if ($category->url == $id) - return $this->get_category((int)$category->id); - - return false; - } - - // Добавление категории - public function add_category($category) - { - $category = (array)$category; - if(empty($category['url'])) - { - $category['url'] = preg_replace("/[\s]+/ui", '_', $category['name']); - $category['url'] = strtolower(preg_replace("/[^0-9a-zа-я_]+/ui", '', $category['url'])); - } - - // Если есть категория с таким URL, добавляем к нему число - while($this->get_category((string)$category['url'])) - { - if(preg_match('/(.+)_([0-9]+)$/', $category['url'], $parts)) - $category['url'] = $parts[1].'_'.($parts[2]+1); - else - $category['url'] = $category['url'].'_2'; - } - - $this->db->query("INSERT INTO __categories SET ?%", $category); - $id = $this->db->insert_id(); - $this->db->query("UPDATE __categories SET position=id WHERE id=?", $id); - unset($this->categories_tree); - unset($this->all_categories); - return $id; - } - - // Изменение категории - public function update_category($id, $category) - { - $query = $this->db->placehold("UPDATE __categories SET ?% WHERE id=? LIMIT 1", $category, intval($id)); - $this->db->query($query); - unset($this->categories_tree); - unset($this->all_categories); - return intval($id); - } - - // Удаление категории - public function delete_category($ids) - { - $ids = (array) $ids; - foreach($ids as $id) - { - if($category = $this->get_category(intval($id))) - $this->delete_image($category->children); - if(!empty($category->children)) - { - $query = $this->db->placehold("DELETE FROM __categories WHERE id in(?@)", $category->children); - $this->db->query($query); - $query = $this->db->placehold("DELETE FROM __products_categories WHERE category_id in(?@)", $category->children); - $this->db->query($query); - } - } - unset($this->categories_tree); - unset($this->all_categories); - return $id; - } - - // Добавить категорию к заданному товару - public function add_product_category($product_id, $category_id, $position=0) - { - $query = $this->db->placehold("INSERT IGNORE INTO __products_categories SET product_id=?, category_id=?, position=?", $product_id, $category_id, $position); - $this->db->query($query); - } - - // Удалить категорию заданного товара - public function delete_product_category($product_id, $category_id) - { - $query = $this->db->placehold("DELETE FROM __products_categories WHERE product_id=? AND category_id=? LIMIT 1", intval($product_id), intval($category_id)); - $this->db->query($query); - } - - // Удалить изображение категории - public function delete_image($categories_ids) - { - $categories_ids = (array) $categories_ids; - $query = $this->db->placehold("SELECT image FROM __categories WHERE id in(?@)", $categories_ids); - $this->db->query($query); - $filenames = $this->db->results('image'); - if(!empty($filenames)) - { - $query = $this->db->placehold("UPDATE __categories SET image=NULL WHERE id in(?@)", $categories_ids); - $this->db->query($query); - foreach($filenames as $filename) - { - $query = $this->db->placehold("SELECT count(*) as count FROM __categories WHERE image=?", $filename); - $this->db->query($query); - $count = $this->db->result('count'); - if($count == 0) - { - @unlink($this->config->root_dir.$this->config->categories_images_dir.$filename); - } - } - unset($this->categories_tree); - unset($this->all_categories); - } - } - - - // Инициализация категорий, после которой категории будем выбирать из локальной переменной - private function init_categories() - { - // Дерево категорий - $tree = new stdClass(); - $tree->subcategories = array(); - - // Указатели на узлы дерева - $pointers = array(); - $pointers[0] = &$tree; - $pointers[0]->path = array(); - $pointers[0]->level = 0; - - // Выбираем все категории - $query = $this->db->placehold("SELECT c.id, c.parent_id, c.name, c.description, c.url, c.meta_title, c.meta_keywords, c.meta_description, c.image, c.visible, c.position + // Список указателей на категории в дереве категорий (ключ = id категории) + private $all_categories; + // Дерево категорий + private $categories_tree; + + // Функция возвращает массив категорий + public function get_categories($filter = array()) + { + if (!isset($this->categories_tree)) { + $this->init_categories(); + } + + if (!empty($filter['product_id'])) { + $query = $this->db->placehold("SELECT category_id FROM __products_categories WHERE product_id in(?@) ORDER BY position", (array)$filter['product_id']); + $this->db->query($query); + $categories_ids = $this->db->results('category_id'); + $result = array(); + foreach ($categories_ids as $id) { + if (isset($this->all_categories[$id])) { + $result[$id] = $this->all_categories[$id]; + } + } + return $result; + } + + return $this->all_categories; + } + + // Функция возвращает id категорий для заданного товара + public function get_product_categories($product_id) + { + $query = $this->db->placehold("SELECT product_id, category_id, position FROM __products_categories WHERE product_id in(?@) ORDER BY position", (array)$product_id); + $this->db->query($query); + return $this->db->results(); + } + + // Функция возвращает id категорий для всех товаров + public function get_products_categories() + { + $query = $this->db->placehold("SELECT product_id, category_id, position FROM __products_categories ORDER BY position"); + $this->db->query($query); + return $this->db->results(); + } + + // Функция возвращает дерево категорий + public function get_categories_tree() + { + if (!isset($this->categories_tree)) { + $this->init_categories(); + } + + return $this->categories_tree; + } + + // Функция возвращает заданную категорию + public function get_category($id) + { + if (!isset($this->all_categories)) { + $this->init_categories(); + } + if (is_int($id) && array_key_exists(intval($id), $this->all_categories)) { + return $category = $this->all_categories[intval($id)]; + } elseif (is_string($id)) { + foreach ($this->all_categories as $category) { + if ($category->url == $id) { + return $this->get_category((int)$category->id); + } + } + } + + return false; + } + + // Добавление категории + public function add_category($category) + { + $category = (array)$category; + if (empty($category['url'])) { + $category['url'] = preg_replace("/[\s]+/ui", '_', $category['name']); + $category['url'] = strtolower(preg_replace("/[^0-9a-zа-я_]+/ui", '', $category['url'])); + } + + // Если есть категория с таким URL, добавляем к нему число + while ($this->get_category((string)$category['url'])) { + if (preg_match('/(.+)_([0-9]+)$/', $category['url'], $parts)) { + $category['url'] = $parts[1].'_'.($parts[2]+1); + } else { + $category['url'] = $category['url'].'_2'; + } + } + + $this->db->query("INSERT INTO __categories SET ?%", $category); + $id = $this->db->insert_id(); + $this->db->query("UPDATE __categories SET position=id WHERE id=?", $id); + unset($this->categories_tree); + unset($this->all_categories); + return $id; + } + + // Изменение категории + public function update_category($id, $category) + { + $query = $this->db->placehold("UPDATE __categories SET ?% WHERE id=? LIMIT 1", $category, intval($id)); + $this->db->query($query); + unset($this->categories_tree); + unset($this->all_categories); + return intval($id); + } + + // Удаление категории + public function delete_category($ids) + { + $ids = (array) $ids; + foreach ($ids as $id) { + if ($category = $this->get_category(intval($id))) { + $this->delete_image($category->children); + } + if (!empty($category->children)) { + $query = $this->db->placehold("DELETE FROM __categories WHERE id in(?@)", $category->children); + $this->db->query($query); + $query = $this->db->placehold("DELETE FROM __products_categories WHERE category_id in(?@)", $category->children); + $this->db->query($query); + } + } + unset($this->categories_tree); + unset($this->all_categories); + return $id; + } + + // Добавить категорию к заданному товару + public function add_product_category($product_id, $category_id, $position=0) + { + $query = $this->db->placehold("INSERT IGNORE INTO __products_categories SET product_id=?, category_id=?, position=?", $product_id, $category_id, $position); + $this->db->query($query); + } + + // Удалить категорию заданного товара + public function delete_product_category($product_id, $category_id) + { + $query = $this->db->placehold("DELETE FROM __products_categories WHERE product_id=? AND category_id=? LIMIT 1", intval($product_id), intval($category_id)); + $this->db->query($query); + } + + // Удалить изображение категории + public function delete_image($categories_ids) + { + $categories_ids = (array) $categories_ids; + $query = $this->db->placehold("SELECT image FROM __categories WHERE id in(?@)", $categories_ids); + $this->db->query($query); + $filenames = $this->db->results('image'); + if (!empty($filenames)) { + $query = $this->db->placehold("UPDATE __categories SET image=NULL WHERE id in(?@)", $categories_ids); + $this->db->query($query); + foreach ($filenames as $filename) { + $query = $this->db->placehold("SELECT count(*) as count FROM __categories WHERE image=?", $filename); + $this->db->query($query); + $count = $this->db->result('count'); + if ($count == 0) { + @unlink($this->config->root_dir.$this->config->categories_images_dir.$filename); + } + } + unset($this->categories_tree); + unset($this->all_categories); + } + } + + + // Инициализация категорий, после которой категории будем выбирать из локальной переменной + private function init_categories() + { + // Дерево категорий + $tree = new stdClass(); + $tree->subcategories = array(); + + // Указатели на узлы дерева + $pointers = array(); + $pointers[0] = &$tree; + $pointers[0]->path = array(); + $pointers[0]->level = 0; + + // Выбираем все категории + $query = $this->db->placehold("SELECT c.id, c.parent_id, c.name, c.description, c.url, c.meta_title, c.meta_keywords, c.meta_description, c.image, c.visible, c.position FROM __categories c ORDER BY c.parent_id, c.position"); - // Выбор категорий с подсчетом количества товаров для каждой. Может тормозить при большом количестве товаров. - // $query = $this->db->placehold("SELECT c.id, c.parent_id, c.name, c.description, c.url, c.meta_title, c.meta_keywords, c.meta_description, c.image, c.visible, c.position, COUNT(p.id) as products_count - // FROM __categories c LEFT JOIN __products_categories pc ON pc.category_id=c.id LEFT JOIN __products p ON p.id=pc.product_id AND p.visible GROUP BY c.id ORDER BY c.parent_id, c.position"); - - - $this->db->query($query); - $categories = $this->db->results(); - - $finish = false; - // Не кончаем, пока не кончатся категории, или пока ниодну из оставшихся некуда приткнуть - while(!empty($categories) && !$finish) - { - $flag = false; - // Проходим все выбранные категории - foreach($categories as $k=>$category) - { - if(isset($pointers[$category->parent_id])) - { - // В дерево категорий (через указатель) добавляем текущую категорию - $pointers[$category->id] = $pointers[$category->parent_id]->subcategories[] = $category; - - // Путь к текущей категории - $curr = $pointers[$category->id]; - $pointers[$category->id]->path = array_merge((array)$pointers[$category->parent_id]->path, array($curr)); - - // Уровень вложенности категории - $pointers[$category->id]->level = 1+$pointers[$category->parent_id]->level; - - // Убираем использованную категорию из массива категорий - unset($categories[$k]); - $flag = true; - } - } - if(!$flag) $finish = true; - } - - // Для каждой категории id всех ее деток узнаем - $ids = array_reverse(array_keys($pointers)); - foreach($ids as $id) - { - if($id>0) - { - $pointers[$id]->children[] = $id; - - if(isset($pointers[$pointers[$id]->parent_id]->children)) - $pointers[$pointers[$id]->parent_id]->children = array_merge($pointers[$id]->children, $pointers[$pointers[$id]->parent_id]->children); - else - $pointers[$pointers[$id]->parent_id]->children = $pointers[$id]->children; - - // Добавляем количество товаров к родительской категории, если текущая видима - // if(isset($pointers[$pointers[$id]->parent_id]) && $pointers[$id]->visible) - // $pointers[$pointers[$id]->parent_id]->products_count += $pointers[$id]->products_count; - } - } - unset($pointers[0]); - unset($ids); - - $this->categories_tree = $tree->subcategories; - $this->all_categories = $pointers; - } + // Выбор категорий с подсчетом количества товаров для каждой. Может тормозить при большом количестве товаров. + // $query = $this->db->placehold("SELECT c.id, c.parent_id, c.name, c.description, c.url, c.meta_title, c.meta_keywords, c.meta_description, c.image, c.visible, c.position, COUNT(p.id) as products_count + // FROM __categories c LEFT JOIN __products_categories pc ON pc.category_id=c.id LEFT JOIN __products p ON p.id=pc.product_id AND p.visible GROUP BY c.id ORDER BY c.parent_id, c.position"); + + + $this->db->query($query); + $categories = $this->db->results(); + + $finish = false; + // Не кончаем, пока не кончатся категории, или пока ниодну из оставшихся некуда приткнуть + while (!empty($categories) && !$finish) { + $flag = false; + // Проходим все выбранные категории + foreach ($categories as $k=>$category) { + if (isset($pointers[$category->parent_id])) { + // В дерево категорий (через указатель) добавляем текущую категорию + $pointers[$category->id] = $pointers[$category->parent_id]->subcategories[] = $category; + + // Путь к текущей категории + $curr = $pointers[$category->id]; + $pointers[$category->id]->path = array_merge((array)$pointers[$category->parent_id]->path, array($curr)); + + // Уровень вложенности категории + $pointers[$category->id]->level = 1+$pointers[$category->parent_id]->level; + + // Убираем использованную категорию из массива категорий + unset($categories[$k]); + $flag = true; + } + } + if (!$flag) { + $finish = true; + } + } + + // Для каждой категории id всех ее деток узнаем + $ids = array_reverse(array_keys($pointers)); + foreach ($ids as $id) { + if ($id>0) { + $pointers[$id]->children[] = $id; + + if (isset($pointers[$pointers[$id]->parent_id]->children)) { + $pointers[$pointers[$id]->parent_id]->children = array_merge($pointers[$id]->children, $pointers[$pointers[$id]->parent_id]->children); + } else { + $pointers[$pointers[$id]->parent_id]->children = $pointers[$id]->children; + } + + // Добавляем количество товаров к родительской категории, если текущая видима + // if(isset($pointers[$pointers[$id]->parent_id]) && $pointers[$id]->visible) + // $pointers[$pointers[$id]->parent_id]->products_count += $pointers[$id]->products_count; + } + } + unset($pointers[0]); + unset($ids); + + $this->categories_tree = $tree->subcategories; + $this->all_categories = $pointers; + } } diff --git a/api/Comments.php b/api/Comments.php index 1a1d173..b1a0a2e 100755 --- a/api/Comments.php +++ b/api/Comments.php @@ -14,61 +14,69 @@ class Comments extends Simpla { - // Возвращает комментарий по id - public function get_comment($id) - { - $query = $this->db->placehold("SELECT c.id, c.object_id, c.name, c.ip, c.type, c.text, c.date, c.approved FROM __comments c WHERE id=? LIMIT 1", intval($id)); - - if($this->db->query($query)) - return $this->db->result(); - else - return false; - } - - // Возвращает комментарии, удовлетворяющие фильтру - public function get_comments($filter = array()) - { - // По умолчанию - $limit = 0; - $page = 1; - $object_id_filter = ''; - $type_filter = ''; - $keyword_filter = ''; - $approved_filter = ''; - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - if(isset($filter['ip'])) - $ip = $this->db->placehold("OR c.ip=?", $filter['ip']); - if(isset($filter['approved'])) - $approved_filter = $this->db->placehold("AND (c.approved=? $ip)", intval($filter['approved'])); - - if($limit) - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - else - $sql_limit = ''; - - if(!empty($filter['object_id'])) - $object_id_filter = $this->db->placehold('AND c.object_id in(?@)', (array)$filter['object_id']); - - if(!empty($filter['type'])) - $type_filter = $this->db->placehold('AND c.type=?', $filter['type']); - - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND c.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR c.text LIKE "%'.$this->db->escape(trim($keyword)).'%" '); - } - - - $sort='DESC'; - - $query = $this->db->placehold("SELECT c.id, c.object_id, c.ip, c.name, c.text, c.type, c.date, c.approved + // Возвращает комментарий по id + public function get_comment($id) + { + $query = $this->db->placehold("SELECT c.id, c.object_id, c.name, c.ip, c.type, c.text, c.date, c.approved FROM __comments c WHERE id=? LIMIT 1", intval($id)); + + if ($this->db->query($query)) { + return $this->db->result(); + } else { + return false; + } + } + + // Возвращает комментарии, удовлетворяющие фильтру + public function get_comments($filter = array()) + { + // По умолчанию + $limit = 0; + $page = 1; + $object_id_filter = ''; + $type_filter = ''; + $keyword_filter = ''; + $approved_filter = ''; + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + if (isset($filter['ip'])) { + $ip = $this->db->placehold("OR c.ip=?", $filter['ip']); + } + if (isset($filter['approved'])) { + $approved_filter = $this->db->placehold("AND (c.approved=? $ip)", intval($filter['approved'])); + } + + if ($limit) { + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + } else { + $sql_limit = ''; + } + + if (!empty($filter['object_id'])) { + $object_id_filter = $this->db->placehold('AND c.object_id in(?@)', (array)$filter['object_id']); + } + + if (!empty($filter['type'])) { + $type_filter = $this->db->placehold('AND c.type=?', $filter['type']); + } + + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND c.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR c.text LIKE "%'.$this->db->escape(trim($keyword)).'%" '); + } + } + + + $sort='DESC'; + + $query = $this->db->placehold("SELECT c.id, c.object_id, c.ip, c.name, c.text, c.type, c.date, c.approved FROM __comments c WHERE 1 $object_id_filter @@ -78,35 +86,38 @@ public function get_comments($filter = array()) ORDER BY id $sort $sql_limit"); - $this->db->query($query); - return $this->db->results(); - } - - // Количество комментариев, удовлетворяющих фильтру - public function count_comments($filter = array()) - { - $object_id_filter = ''; - $type_filter = ''; - $approved_filter = ''; - $keyword_filter = ''; - - if(!empty($filter['object_id'])) - $object_id_filter = $this->db->placehold('AND c.object_id in(?@)', (array)$filter['object_id']); - - if(!empty($filter['type'])) - $type_filter = $this->db->placehold('AND c.type=?', $filter['type']); - - if(isset($filter['approved'])) - $approved_filter = $this->db->placehold('AND c.approved=?', intval($filter['approved'])); - - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND c.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR c.text LIKE "%'.$this->db->escape(trim($keyword)).'%" '); - } - - $query = $this->db->placehold("SELECT count(distinct c.id) as count + $this->db->query($query); + return $this->db->results(); + } + + // Количество комментариев, удовлетворяющих фильтру + public function count_comments($filter = array()) + { + $object_id_filter = ''; + $type_filter = ''; + $approved_filter = ''; + $keyword_filter = ''; + + if (!empty($filter['object_id'])) { + $object_id_filter = $this->db->placehold('AND c.object_id in(?@)', (array)$filter['object_id']); + } + + if (!empty($filter['type'])) { + $type_filter = $this->db->placehold('AND c.type=?', $filter['type']); + } + + if (isset($filter['approved'])) { + $approved_filter = $this->db->placehold('AND c.approved=?', intval($filter['approved'])); + } + + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND c.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR c.text LIKE "%'.$this->db->escape(trim($keyword)).'%" '); + } + } + + $query = $this->db->placehold("SELECT count(distinct c.id) as count FROM __comments c WHERE 1 $object_id_filter @@ -114,48 +125,46 @@ public function count_comments($filter = array()) $keyword_filter $approved_filter", $this->settings->date_format); - $this->db->query($query); - return $this->db->result('count'); - - } + $this->db->query($query); + return $this->db->result('count'); + } - // Добавление комментария - public function add_comment($comment) - { - $query = $this->db->placehold('INSERT INTO __comments + // Добавление комментария + public function add_comment($comment) + { + $query = $this->db->placehold('INSERT INTO __comments SET ?%, date = NOW()', - $comment); - - if(!$this->db->query($query)) - return false; - - $id = $this->db->insert_id(); - return $id; - } - - // Изменение комментария - public function update_comment($id, $comment) - { - $date_query = ''; - if(isset($comment->date)) - { - $date = $comment->date; - unset($comment->date); - $date_query = $this->db->placehold(', date=STR_TO_DATE(?, ?)', $date, $this->settings->date_format); - } - $query = $this->db->placehold("UPDATE __comments SET ?% $date_query WHERE id in(?@) LIMIT 1", $comment, (array)$id); - $this->db->query($query); - return $id; - } - - // Удаление комментария - public function delete_comment($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __comments WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - } - } + $comment); + + if (!$this->db->query($query)) { + return false; + } + + $id = $this->db->insert_id(); + return $id; + } + + // Изменение комментария + public function update_comment($id, $comment) + { + $date_query = ''; + if (isset($comment->date)) { + $date = $comment->date; + unset($comment->date); + $date_query = $this->db->placehold(', date=STR_TO_DATE(?, ?)', $date, $this->settings->date_format); + } + $query = $this->db->placehold("UPDATE __comments SET ?% $date_query WHERE id in(?@) LIMIT 1", $comment, (array)$id); + $this->db->query($query); + return $id; + } + + // Удаление комментария + public function delete_comment($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __comments WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + } + } } diff --git a/api/Config.php b/api/Config.php index b2d2c25..a8297b5 100755 --- a/api/Config.php +++ b/api/Config.php @@ -13,118 +13,118 @@ class Config { - public $version = '2.3.7'; - - // Файл для хранения настроек - public $config_file = 'config/config.php'; - - private $vars = array(); - - // В конструкторе записываем настройки файла в переменные этого класса - // для удобного доступа к ним. Например: $simpla->config->db_user - public function __construct() - { - // Читаем настройки из дефолтного файла - $ini = parse_ini_file(dirname(dirname(__FILE__)).'/'.$this->config_file); - // Записываем настройку как переменную класса - foreach($ini as $var=>$value) - $this->vars[$var] = $value; - - // Вычисляем DOCUMENT_ROOT вручную, так как иногда в нем находится что-то левое - $localpath = getenv("SCRIPT_NAME"); - $absolutepath = getenv("SCRIPT_FILENAME"); - $_SERVER['DOCUMENT_ROOT']=substr($absolutepath,0,strpos($absolutepath,$localpath)); - - // Адрес сайта - тоже одна из настроек, но вычисляем его автоматически, а не берем из файла - $script_dir1 = realpath(dirname(dirname(__FILE__))); - $script_dir2 = realpath($_SERVER['DOCUMENT_ROOT']); - $subdir = trim(substr($script_dir1, strlen($script_dir2)), "/\\"); - - if (!isset($_SERVER['HTTP_HOST'])) - $_SERVER['HTTP_HOST'] = getenv('HTTP_HOST'); - - $this->vars['host'] = rtrim($_SERVER['HTTP_HOST']); - - // Протокол (http OR https) - $protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,5))=='https'? 'https' : 'http'; - if (isset($_SERVER['HTTPS']) && (($_SERVER['HTTPS'] == 'on') || ($_SERVER['HTTPS'] == '1'))) { - $protocol = 'https'; - } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') { - $protocol = 'https'; - } elseif( isset($_SERVER['SERVER_PORT']) && '443' == $_SERVER['SERVER_PORT'] ) { - $protocol = 'https'; - } - - $this->vars['protocol'] = $protocol; - $this->vars['root_url'] = $protocol.'://'.$this->vars['host']; - if(!empty($subdir)) - $this->vars['root_url'] .= '/'.$subdir; - - // Подпапка в которую установлена симпла относительно корня веб-сервера - $this->vars['subfolder'] = $subdir.'/'; - - // Определяем корневую директорию сайта - $this->vars['root_dir'] = dirname(dirname(__FILE__)).'/'; - - // Максимальный размер загружаемых файлов - $max_upload = (int)(ini_get('upload_max_filesize')); - $max_post = (int)(ini_get('post_max_size')); - $memory_limit = (int)(ini_get('memory_limit')); - $this->vars['max_upload_filesize'] = min($max_upload, $max_post, $memory_limit)*1024*1024; - - // Если соль не определена, то будем генировать ее - if(empty($this->vars['salt'])) - { - // Соль (разная для каждой копии сайта, изменяющаяся при изменении config-файла) - $s = stat(dirname(dirname(__FILE__)).'/'.$this->config_file); - $this->vars['salt'] = md5(md5_file(dirname(dirname(__FILE__)).'/'.$this->config_file).$s['dev'].$s['ino'].$s['uid'].$s['mtime']); - } - - - // Часовой пояс - if(!empty($this->vars['php_timezone'])) - { - date_default_timezone_set($this->vars['php_timezone']); - } - elseif(!ini_get('date.timezone')) - { - date_default_timezone_set('UTC'); - } - } - - // Магическим методов возвращаем нужную переменную - public function __get($name) - { - if(isset($this->vars[$name])) - return $this->vars[$name]; - else - return null; - } - - // Магическим методов задаём нужную переменную - public function __set($name, $value) - { - # Запишем конфиги - if(isset($this->vars[$name])) - { - $conf = file_get_contents(dirname(dirname(__FILE__)).'/'.$this->config_file); - $conf = preg_replace("/".$name."\s*=.*\n/i", $name.' = '.$value."\r\n", $conf); - $cf = fopen(dirname(dirname(__FILE__)).'/'.$this->config_file, 'w'); - fwrite($cf, $conf); - fclose($cf); - $this->vars[$name] = $value; - } - } - - public function token($text) - { - return md5($text.$this->salt); - } - - public function check_token($text, $token) - { - if(!empty($token) && $token === $this->token($text)) - return true; - return false; - } + public $version = '2.3.7'; + + // Файл для хранения настроек + public $config_file = 'config/config.php'; + + private $vars = array(); + + // В конструкторе записываем настройки файла в переменные этого класса + // для удобного доступа к ним. Например: $simpla->config->db_user + public function __construct() + { + // Читаем настройки из дефолтного файла + $ini = parse_ini_file(dirname(dirname(__FILE__)).'/'.$this->config_file); + // Записываем настройку как переменную класса + foreach ($ini as $var=>$value) { + $this->vars[$var] = $value; + } + + // Вычисляем DOCUMENT_ROOT вручную, так как иногда в нем находится что-то левое + $localpath = getenv("SCRIPT_NAME"); + $absolutepath = getenv("SCRIPT_FILENAME"); + $_SERVER['DOCUMENT_ROOT']=substr($absolutepath, 0, strpos($absolutepath, $localpath)); + + // Адрес сайта - тоже одна из настроек, но вычисляем его автоматически, а не берем из файла + $script_dir1 = realpath(dirname(dirname(__FILE__))); + $script_dir2 = realpath($_SERVER['DOCUMENT_ROOT']); + $subdir = trim(substr($script_dir1, strlen($script_dir2)), "/\\"); + + if (!isset($_SERVER['HTTP_HOST'])) { + $_SERVER['HTTP_HOST'] = getenv('HTTP_HOST'); + } + + $this->vars['host'] = rtrim($_SERVER['HTTP_HOST']); + + // Протокол (http OR https) + $protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"], 0, 5))=='https'? 'https' : 'http'; + if (isset($_SERVER['HTTPS']) && (($_SERVER['HTTPS'] == 'on') || ($_SERVER['HTTPS'] == '1'))) { + $protocol = 'https'; + } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') { + $protocol = 'https'; + } elseif (isset($_SERVER['SERVER_PORT']) && '443' == $_SERVER['SERVER_PORT']) { + $protocol = 'https'; + } + + $this->vars['protocol'] = $protocol; + $this->vars['root_url'] = $protocol.'://'.$this->vars['host']; + if (!empty($subdir)) { + $this->vars['root_url'] .= '/'.$subdir; + } + + // Подпапка в которую установлена симпла относительно корня веб-сервера + $this->vars['subfolder'] = $subdir.'/'; + + // Определяем корневую директорию сайта + $this->vars['root_dir'] = dirname(dirname(__FILE__)).'/'; + + // Максимальный размер загружаемых файлов + $max_upload = (int)(ini_get('upload_max_filesize')); + $max_post = (int)(ini_get('post_max_size')); + $memory_limit = (int)(ini_get('memory_limit')); + $this->vars['max_upload_filesize'] = min($max_upload, $max_post, $memory_limit)*1024*1024; + + // Если соль не определена, то будем генировать ее + if (empty($this->vars['salt'])) { + // Соль (разная для каждой копии сайта, изменяющаяся при изменении config-файла) + $s = stat(dirname(dirname(__FILE__)).'/'.$this->config_file); + $this->vars['salt'] = md5(md5_file(dirname(dirname(__FILE__)).'/'.$this->config_file).$s['dev'].$s['ino'].$s['uid'].$s['mtime']); + } + + + // Часовой пояс + if (!empty($this->vars['php_timezone'])) { + date_default_timezone_set($this->vars['php_timezone']); + } elseif (!ini_get('date.timezone')) { + date_default_timezone_set('UTC'); + } + } + + // Магическим методов возвращаем нужную переменную + public function __get($name) + { + if (isset($this->vars[$name])) { + return $this->vars[$name]; + } else { + return null; + } + } + + // Магическим методов задаём нужную переменную + public function __set($name, $value) + { + # Запишем конфиги + if (isset($this->vars[$name])) { + $conf = file_get_contents(dirname(dirname(__FILE__)).'/'.$this->config_file); + $conf = preg_replace("/".$name."\s*=.*\n/i", $name.' = '.$value."\r\n", $conf); + $cf = fopen(dirname(dirname(__FILE__)).'/'.$this->config_file, 'w'); + fwrite($cf, $conf); + fclose($cf); + $this->vars[$name] = $value; + } + } + + public function token($text) + { + return md5($text.$this->salt); + } + + public function check_token($text, $token) + { + if (!empty($token) && $token === $this->token($text)) { + return true; + } + return false; + } } diff --git a/api/Coupons.php b/api/Coupons.php index 4538c4b..7596ea3 100755 --- a/api/Coupons.php +++ b/api/Coupons.php @@ -14,71 +14,78 @@ class Coupons extends Simpla { - /* - * - * Функция возвращает купон по его id или url - * (в зависимости от типа аргумента, int - id, string - code) - * @param $id id или code купона - * - */ - public function get_coupon($id) - { - if(gettype($id) == 'string') - $where = $this->db->placehold('WHERE c.code=? ', $id); - else - $where = $this->db->placehold('WHERE c.id=? ', $id); - - $query = $this->db->placehold("SELECT c.id, c.code, c.value, c.type, c.expire, min_order_price, c.single, c.usages, + /* + * + * Функция возвращает купон по его id или url + * (в зависимости от типа аргумента, int - id, string - code) + * @param $id id или code купона + * + */ + public function get_coupon($id) + { + if (gettype($id) == 'string') { + $where = $this->db->placehold('WHERE c.code=? ', $id); + } else { + $where = $this->db->placehold('WHERE c.id=? ', $id); + } + + $query = $this->db->placehold("SELECT c.id, c.code, c.value, c.type, c.expire, min_order_price, c.single, c.usages, ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single)) AS valid FROM __coupons c $where LIMIT 1"); - if($this->db->query($query)) - return $this->db->result(); - else - return false; - } - - /* - * - * Функция возвращает массив купонов, удовлетворяющих фильтру - * @param $filter - * - */ - public function get_coupons($filter = array()) - { - // По умолчанию - $limit = 1000; - $page = 1; - $coupon_id_filter = ''; - $valid_filter = ''; - $keyword_filter = ''; - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - if(!empty($filter['id'])) - $coupon_id_filter = $this->db->placehold('AND c.id in(?@)', (array)$filter['id']); - - if(isset($filter['valid'])) - if($filter['valid']) - $valid_filter = $this->db->placehold('AND ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single))'); - else - $valid_filter = $this->db->placehold('AND NOT ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single))'); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); - } - - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - - $query = $this->db->placehold("SELECT c.id, c.code, c.value, c.type, c.expire, min_order_price, c.single, c.usages, + if ($this->db->query($query)) { + return $this->db->result(); + } else { + return false; + } + } + + /* + * + * Функция возвращает массив купонов, удовлетворяющих фильтру + * @param $filter + * + */ + public function get_coupons($filter = array()) + { + // По умолчанию + $limit = 1000; + $page = 1; + $coupon_id_filter = ''; + $valid_filter = ''; + $keyword_filter = ''; + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + if (!empty($filter['id'])) { + $coupon_id_filter = $this->db->placehold('AND c.id in(?@)', (array)$filter['id']); + } + + if (isset($filter['valid'])) { + if ($filter['valid']) { + $valid_filter = $this->db->placehold('AND ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single))'); + } else { + $valid_filter = $this->db->placehold('AND NOT ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single))'); + } + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); + } + } + + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + + $query = $this->db->placehold("SELECT c.id, c.code, c.value, c.type, c.expire, min_order_price, c.single, c.usages, ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single)) AS valid FROM __coupons c WHERE 1 @@ -88,93 +95,96 @@ public function get_coupons($filter = array()) ORDER BY valid DESC, id DESC $sql_limit", $this->settings->date_format); - $this->db->query($query); - return $this->db->results(); - } - - - /* - * - * Функция вычисляет количество постов, удовлетворяющих фильтру - * @param $filter - * - */ - public function count_coupons($filter = array()) - { - $coupon_id_filter = ''; - $valid_filter = ''; - - if(!empty($filter['id'])) - $coupon_id_filter = $this->db->placehold('AND c.id in(?@)', (array)$filter['id']); - - if(isset($filter['valid'])) - $valid_filter = $this->db->placehold('AND ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single))'); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); - } - - $query = $this->db->placehold("SELECT COUNT(distinct c.id) as count + $this->db->query($query); + return $this->db->results(); + } + + + /* + * + * Функция вычисляет количество постов, удовлетворяющих фильтру + * @param $filter + * + */ + public function count_coupons($filter = array()) + { + $coupon_id_filter = ''; + $valid_filter = ''; + + if (!empty($filter['id'])) { + $coupon_id_filter = $this->db->placehold('AND c.id in(?@)', (array)$filter['id']); + } + + if (isset($filter['valid'])) { + $valid_filter = $this->db->placehold('AND ((DATE(NOW()) <= DATE(c.expire) OR c.expire IS NULL) AND (c.usages=0 OR NOT c.single))'); + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (b.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR b.meta_keywords LIKE "%'.$this->db->escape(trim($keyword)).'%") '); + } + } + + $query = $this->db->placehold("SELECT COUNT(distinct c.id) as count FROM __coupons c WHERE 1 $coupon_id_filter $valid_filter"); - if($this->db->query($query)) - return $this->db->result('count'); - else - return false; - } - - /* - * - * Создание купона - * @param $coupon - * - */ - public function add_coupon($coupon) - { - if(empty($coupon->single)) - $coupon->single = 0; - $query = $this->db->placehold("INSERT INTO __coupons SET ?%", $coupon); - - if(!$this->db->query($query)) - return false; - else - return $this->db->insert_id(); - } - - - /* - * - * Обновить купон(ы) - * @param $id, $coupon - * - */ - public function update_coupon($id, $coupon) - { - $query = $this->db->placehold("UPDATE __coupons SET ?% WHERE id in(?@) LIMIT ?", $coupon, (array)$id, count((array)$id)); - $this->db->query($query); - return $id; - } - - - /* - * - * Удалить купон - * @param $id - * - */ - public function delete_coupon($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __coupons WHERE id=? LIMIT 1", intval($id)); - return $this->db->query($query); - } - } - + if ($this->db->query($query)) { + return $this->db->result('count'); + } else { + return false; + } + } + + /* + * + * Создание купона + * @param $coupon + * + */ + public function add_coupon($coupon) + { + if (empty($coupon->single)) { + $coupon->single = 0; + } + $query = $this->db->placehold("INSERT INTO __coupons SET ?%", $coupon); + + if (!$this->db->query($query)) { + return false; + } else { + return $this->db->insert_id(); + } + } + + + /* + * + * Обновить купон(ы) + * @param $id, $coupon + * + */ + public function update_coupon($id, $coupon) + { + $query = $this->db->placehold("UPDATE __coupons SET ?% WHERE id in(?@) LIMIT ?", $coupon, (array)$id, count((array)$id)); + $this->db->query($query); + return $id; + } + + + /* + * + * Удалить купон + * @param $id + * + */ + public function delete_coupon($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __coupons WHERE id=? LIMIT 1", intval($id)); + return $this->db->query($query); + } + } } diff --git a/api/Database.php b/api/Database.php index 05d21a9..349f7bc 100755 --- a/api/Database.php +++ b/api/Database.php @@ -13,493 +13,471 @@ class Database extends Simpla { - private $mysqli; - private $res; - - /** - * В конструкторе подключаем базу - */ - public function __construct() - { - parent::__construct(); - $this->connect(); - } - - /** - * В деструкторе отсоединяемся от базы - */ - public function __destruct() - { - $this->disconnect(); - } - - /** - * Подключение к базе данных - */ - public function connect() - { - // При повторном вызове возвращаем существующий линк - if(!empty($this->mysqli)) - return $this->mysqli; - // Иначе устанавливаем соединение - else - $this->mysqli = new mysqli($this->config->db_server, $this->config->db_user, $this->config->db_password, $this->config->db_name); - - // Выводим сообщение, в случае ошибки - if($this->mysqli->connect_error) - { - trigger_error("Could not connect to the database: ".$this->mysqli->connect_error, E_USER_WARNING); - return false; - } - // Или настраиваем соединение - else - { - if($this->config->db_charset) - $this->mysqli->query('SET NAMES '.$this->config->db_charset); - if($this->config->db_sql_mode) - $this->mysqli->query('SET SESSION SQL_MODE = "'.$this->config->db_sql_mode.'"'); - if($this->config->db_timezone) - $this->mysqli->query('SET time_zone = "'.$this->config->db_timezone.'"'); - } - return $this->mysqli; - } - - /** - * Закрываем подключение к базе данных - */ - public function disconnect() - { - if(!@$this->mysqli->close()) - return true; - else - return false; - } - - - /** - * Запрос к базе. Обазятелен первый аргумент - текст запроса. - * При указании других аргументов автоматически выполняется placehold() для запроса с подстановкой этих аргументов - */ - public function query() - { - if(is_object($this->res)) - $this->res->free(); - - $args = func_get_args(); - $q = call_user_func_array(array($this, 'placehold'), $args); - return $this->res = $this->mysqli->query($q); - } - - - /** - * Экранирование - */ - public function escape($str) - { - return $this->mysqli->real_escape_string($str); - } - - - /** - * Плейсхолдер для запросов. Пример работы: $query = $db->placehold('SELECT name FROM products WHERE id=?', $id); - */ - public function placehold() - { - $args = func_get_args(); - $tmpl = array_shift($args); - // Заменяем все __ на префикс, но только необрамленные кавычками - $tmpl = preg_replace('/([^"\'0-9a-z_])__([a-z_]+[^"\'])/i', "\$1".$this->config->db_prefix."\$2", $tmpl); - if(!empty($args)) - { - $result = $this->sql_placeholder_ex($tmpl, $args, $error); - if ($result === false) - { - $error = "Placeholder substitution error. Diagnostics: \"$error\""; - trigger_error($error, E_USER_WARNING); - return false; - } - return $result; - } - else - return $tmpl; - } - - - /** - * Возвращает результаты запроса. Необязательный второй аргумент указывает какую колонку возвращать вместо всего массива колонок - */ - public function results($field = null) - { - $results = array(); - if(!$this->res) - { - trigger_error($this->mysqli->error, E_USER_WARNING); - return false; - } - - if($this->res->num_rows == 0) - return array(); - - while($row = $this->res->fetch_object()) - { - if(!empty($field) && isset($row->$field)) - array_push($results, $row->$field); - else - array_push($results, $row); - } - return $results; - } - - /** - * Возвращает первый результат запроса. Необязательный второй аргумент указывает какую колонку возвращать вместо всего массива колонок - */ - public function result($field = null) - { - $result = array(); - if(!$this->res) - { - $this->error_msg = "Could not execute query to database"; - return 0; - } - $row = $this->res->fetch_object(); - if(!empty($field) && isset($row->$field)) - return $row->$field; - elseif(!empty($field) && !isset($row->$field)) - return false; - else - return $row; - } - - /** - * Возвращает последний вставленный id - */ - public function insert_id() - { - return $this->mysqli->insert_id; - } - - /** - * Возвращает количество выбранных строк - */ - public function num_rows() - { - return $this->res->num_rows; - } - - /** - * Возвращает количество затронутых строк - */ - public function affected_rows() - { - return $this->mysqli->affected_rows; - } - - /** - * Компиляция плейсхолдера - */ - private function sql_compile_placeholder($tmpl) - { - $compiled = array(); - $p = 0; // текущая позиция в строке - $i = 0; // счетчик placeholder-ов - $has_named = false; - while(false !== ($start = $p = strpos($tmpl, "?", $p))) - { - // Определяем тип placeholder-а. - switch ($c = substr($tmpl, ++$p, 1)) - { - case '%': case '@': case '#': - $type = $c; ++$p; break; - default: - $type = ''; break; - } - // Проверяем, именованный ли это placeholder: "?keyname" - if (preg_match('/^((?:[^\s[:punct:]]|_)+)/', substr($tmpl, $p), $pock)) - { - $key = $pock[1]; - if ($type != '#') - $has_named = true; - $p += strlen($key); - } - else - { - $key = $i; - if ($type != '#') - $i++; - } - // Сохранить запись о placeholder-е. - $compiled[] = array($key, $type, $start, $p - $start); - } - return array($compiled, $tmpl, $has_named); - } - - /** - * Выполнение плейсхолдера - */ - private function sql_placeholder_ex($tmpl, $args, &$errormsg) - { - // Запрос уже разобран?.. Если нет, разбираем. - if (is_array($tmpl)) - $compiled = $tmpl; - else - $compiled = $this->sql_compile_placeholder($tmpl); - - list ($compiled, $tmpl, $has_named) = $compiled; - - // Если есть хотя бы один именованный placeholder, используем - // первый аргумент в качестве ассоциативного массива. - if ($has_named) - $args = @$args[0]; - - // Выполняем все замены в цикле. - $p = 0; // текущее положение в строке - $out = ''; // результирующая строка - $error = false; // были ошибки? - - foreach ($compiled as $num=>$e) - { - list ($key, $type, $start, $length) = $e; - - // Pre-string. - $out .= substr($tmpl, $p, $start - $p); - $p = $start + $length; - - $repl = ''; // текст для замены текущего placeholder-а - $errmsg = ''; // сообщение об ошибке для этого placeholder-а - do { - // Это placeholder-константа? - if ($type === '#') - { - $repl = @constant($key); - if (NULL === $repl) - $error = $errmsg = "UNKNOWN_CONSTANT_$key"; - break; - } - // Обрабатываем ошибку. - if (!isset($args[$key])) - { - $error = $errmsg = "UNKNOWN_PLACEHOLDER_$key"; - break; - } - // Вставляем значение в соответствии с типом placeholder-а. - $a = $args[$key]; - if ($type === '') - { - // Скалярный placeholder. - if (is_array($a)) - { - $error = $errmsg = "NOT_A_SCALAR_PLACEHOLDER_$key"; - break; - } - $repl = is_int($a) || is_float($a) ? str_replace(',', '.', $a) : "'".addslashes($a)."'"; - break; - } - // Иначе это массив или список. - if(is_object($a)) - $a = get_object_vars($a); - - if (!is_array($a)) - { - $error = $errmsg = "NOT_AN_ARRAY_PLACEHOLDER_$key"; - break; - } - if ($type === '@') - { - // Это список. - foreach ($a as $v) - { - if(is_null($v)) - $r = "NULL"; - else - $r = "'".@addslashes($v)."'"; - - $repl .= ($repl===''? "" : ",").$r; - } - } - elseif ($type === '%') - { - // Это набор пар ключ=>значение. - $lerror = array(); - foreach ($a as $k=>$v) - { - if (!is_string($k)) - $lerror[$k] = "NOT_A_STRING_KEY_{$k}_FOR_PLACEHOLDER_$key"; - else - $k = preg_replace('/[^a-zA-Z0-9_]/', '_', $k); - - if(is_null($v)) - $r = "=NULL"; - else - $r = "='".@addslashes($v)."'"; - - $repl .= ($repl===''? "" : ", ").$k.$r; - } - // Если была ошибка, составляем сообщение. - if (count($lerror)) - { - $repl = ''; - foreach ($a as $k=>$v) - { - if (isset($lerror[$k])) - { - $repl .= ($repl===''? "" : ", ").$lerror[$k]; - } - else - { - $k = preg_replace('/[^a-zA-Z0-9_-]/', '_', $k); - $repl .= ($repl===''? "" : ", ").$k."=?"; - } - } - $error = $errmsg = $repl; - } - } - } while (false); - if ($errmsg) $compiled[$num]['error'] = $errmsg; - if (!$error) $out .= $repl; - } - $out .= substr($tmpl, $p); - - // Если возникла ошибка, переделываем результирующую строку - // в сообщение об ошибке (расставляем диагностические строки - // вместо ошибочных placeholder-ов). - if ($error) - { - $out = ''; - $p = 0; // текущая позиция - foreach ($compiled as $num=>$e) - { - list ($key, $type, $start, $length) = $e; - $out .= substr($tmpl, $p, $start - $p); - $p = $start + $length; - if (isset($e['error'])) - { - $out .= $e['error']; - } - else - { - $out .= substr($tmpl, $start, $length); - } - } - // Последняя часть строки. - $out .= substr($tmpl, $p); - $errormsg = $out; - return false; - } - else - { - $errormsg = false; - return $out; - } - } - - public function dump($filename) - { - $h = fopen($filename, 'w'); - $q = $this->placehold("SHOW FULL TABLES LIKE '__%';"); - $result = $this->mysqli->query($q); - while($row = $result->fetch_row()) - { - if($row[1] == 'BASE TABLE') - $this->dump_table($row[0], $h); - } - fclose($h); - } - - public function restore($filename) - { - $templine = ''; - $h = fopen($filename, 'r'); - - // Loop through each line - if($h) - { - while(!feof($h)) - { - $line = fgets($h); - // Only continue if it's not a comment - if (substr($line, 0, 2) != '--' && $line != '') - { - // Add this line to the current segment - $templine .= $line; - // If it has a semicolon at the end, it's the end of the query - if (substr(trim($line), -1, 1) == ';') - { - // Perform the query - $this->query($templine) or print('Error performing query \''.$templine.'\': '.$this->mysqli->error.'

'); - // Reset temp variable to empty - $templine = ''; - } - } - } - } - fclose($h); - } - - - private function dump_table($table, $h) - { - $sql = "SELECT * FROM `$table`;"; - $result = $this->mysqli->query($sql); - if($result) - { - $table_no_prefix = preg_replace('/^('.$this->config->db_prefix.')/i', "__", $table); - fwrite($h, "/* Data for table $table_no_prefix */\n"); - fwrite($h, "TRUNCATE TABLE `$table_no_prefix`;\n"); - - $num_rows = $result->num_rows; - $num_fields = $this->mysqli->field_count; - - if($num_rows > 0) - { - $field_type=array(); - $field_name = array(); - $meta = $result->fetch_fields(); - foreach($meta as $m) - { - array_push($field_type, $m->type); - array_push($field_name, $m->name); - } - $fields = implode('`, `', $field_name); - fwrite($h, "INSERT INTO `$table_no_prefix` (`$fields`) VALUES\n"); - $index=0; - while( $row = $result->fetch_row()) - { - fwrite($h, "("); - for( $i=0; $i < $num_fields; $i++) - { - if( is_null( $row[$i])) - fwrite($h, "null"); - else - { - switch( $field_type[$i]) - { - case 'int': - fwrite($h, $row[$i]); - break; - case 'string': - case 'blob' : - default: - fwrite($h, "'". $this->mysqli->real_escape_string($row[$i])."'"); - - } - } - if( $i < $num_fields-1) - fwrite($h, ","); - } - fwrite($h, ")"); - - if( $index < $num_rows-1) - fwrite($h, ","); - else - fwrite($h, ";"); - fwrite($h, "\n"); - - $index++; - } - } - $result->free(); - } - fwrite($h, "\n"); - } + private $mysqli; + private $res; + + /** + * В конструкторе подключаем базу + */ + public function __construct() + { + parent::__construct(); + $this->connect(); + } + + /** + * В деструкторе отсоединяемся от базы + */ + public function __destruct() + { + $this->disconnect(); + } + + /** + * Подключение к базе данных + */ + public function connect() + { + // При повторном вызове возвращаем существующий линк + if (!empty($this->mysqli)) { + return $this->mysqli; + } + // Иначе устанавливаем соединение + else { + $this->mysqli = new mysqli($this->config->db_server, $this->config->db_user, $this->config->db_password, $this->config->db_name); + } + + // Выводим сообщение, в случае ошибки + if ($this->mysqli->connect_error) { + trigger_error("Could not connect to the database: ".$this->mysqli->connect_error, E_USER_WARNING); + return false; + } + // Или настраиваем соединение + else { + if ($this->config->db_charset) { + $this->mysqli->query('SET NAMES '.$this->config->db_charset); + } + if ($this->config->db_sql_mode) { + $this->mysqli->query('SET SESSION SQL_MODE = "'.$this->config->db_sql_mode.'"'); + } + if ($this->config->db_timezone) { + $this->mysqli->query('SET time_zone = "'.$this->config->db_timezone.'"'); + } + } + return $this->mysqli; + } + + /** + * Закрываем подключение к базе данных + */ + public function disconnect() + { + if (!@$this->mysqli->close()) { + return true; + } else { + return false; + } + } + + + /** + * Запрос к базе. Обазятелен первый аргумент - текст запроса. + * При указании других аргументов автоматически выполняется placehold() для запроса с подстановкой этих аргументов + */ + public function query() + { + if (is_object($this->res)) { + $this->res->free(); + } + + $args = func_get_args(); + $q = call_user_func_array(array($this, 'placehold'), $args); + return $this->res = $this->mysqli->query($q); + } + + + /** + * Экранирование + */ + public function escape($str) + { + return $this->mysqli->real_escape_string($str); + } + + + /** + * Плейсхолдер для запросов. Пример работы: $query = $db->placehold('SELECT name FROM products WHERE id=?', $id); + */ + public function placehold() + { + $args = func_get_args(); + $tmpl = array_shift($args); + // Заменяем все __ на префикс, но только необрамленные кавычками + $tmpl = preg_replace('/([^"\'0-9a-z_])__([a-z_]+[^"\'])/i', "\$1".$this->config->db_prefix."\$2", $tmpl); + if (!empty($args)) { + $result = $this->sql_placeholder_ex($tmpl, $args, $error); + if ($result === false) { + $error = "Placeholder substitution error. Diagnostics: \"$error\""; + trigger_error($error, E_USER_WARNING); + return false; + } + return $result; + } else { + return $tmpl; + } + } + + + /** + * Возвращает результаты запроса. Необязательный второй аргумент указывает какую колонку возвращать вместо всего массива колонок + */ + public function results($field = null) + { + $results = array(); + if (!$this->res) { + trigger_error($this->mysqli->error, E_USER_WARNING); + return false; + } + + if ($this->res->num_rows == 0) { + return array(); + } + + while ($row = $this->res->fetch_object()) { + if (!empty($field) && isset($row->$field)) { + array_push($results, $row->$field); + } else { + array_push($results, $row); + } + } + return $results; + } + + /** + * Возвращает первый результат запроса. Необязательный второй аргумент указывает какую колонку возвращать вместо всего массива колонок + */ + public function result($field = null) + { + $result = array(); + if (!$this->res) { + $this->error_msg = "Could not execute query to database"; + return 0; + } + $row = $this->res->fetch_object(); + if (!empty($field) && isset($row->$field)) { + return $row->$field; + } elseif (!empty($field) && !isset($row->$field)) { + return false; + } else { + return $row; + } + } + + /** + * Возвращает последний вставленный id + */ + public function insert_id() + { + return $this->mysqli->insert_id; + } + + /** + * Возвращает количество выбранных строк + */ + public function num_rows() + { + return $this->res->num_rows; + } + + /** + * Возвращает количество затронутых строк + */ + public function affected_rows() + { + return $this->mysqli->affected_rows; + } + + /** + * Компиляция плейсхолдера + */ + private function sql_compile_placeholder($tmpl) + { + $compiled = array(); + $p = 0; // текущая позиция в строке + $i = 0; // счетчик placeholder-ов + $has_named = false; + while (false !== ($start = $p = strpos($tmpl, "?", $p))) { + // Определяем тип placeholder-а. + switch ($c = substr($tmpl, ++$p, 1)) { + case '%': case '@': case '#': + $type = $c; ++$p; break; + default: + $type = ''; break; + } + // Проверяем, именованный ли это placeholder: "?keyname" + if (preg_match('/^((?:[^\s[:punct:]]|_)+)/', substr($tmpl, $p), $pock)) { + $key = $pock[1]; + if ($type != '#') { + $has_named = true; + } + $p += strlen($key); + } else { + $key = $i; + if ($type != '#') { + $i++; + } + } + // Сохранить запись о placeholder-е. + $compiled[] = array($key, $type, $start, $p - $start); + } + return array($compiled, $tmpl, $has_named); + } + + /** + * Выполнение плейсхолдера + */ + private function sql_placeholder_ex($tmpl, $args, &$errormsg) + { + // Запрос уже разобран?.. Если нет, разбираем. + if (is_array($tmpl)) { + $compiled = $tmpl; + } else { + $compiled = $this->sql_compile_placeholder($tmpl); + } + + list($compiled, $tmpl, $has_named) = $compiled; + + // Если есть хотя бы один именованный placeholder, используем + // первый аргумент в качестве ассоциативного массива. + if ($has_named) { + $args = @$args[0]; + } + + // Выполняем все замены в цикле. + $p = 0; // текущее положение в строке + $out = ''; // результирующая строка + $error = false; // были ошибки? + + foreach ($compiled as $num=>$e) { + list($key, $type, $start, $length) = $e; + + // Pre-string. + $out .= substr($tmpl, $p, $start - $p); + $p = $start + $length; + + $repl = ''; // текст для замены текущего placeholder-а + $errmsg = ''; // сообщение об ошибке для этого placeholder-а + do { + // Это placeholder-константа? + if ($type === '#') { + $repl = @constant($key); + if (null === $repl) { + $error = $errmsg = "UNKNOWN_CONSTANT_$key"; + } + break; + } + // Обрабатываем ошибку. + if (!isset($args[$key])) { + $error = $errmsg = "UNKNOWN_PLACEHOLDER_$key"; + break; + } + // Вставляем значение в соответствии с типом placeholder-а. + $a = $args[$key]; + if ($type === '') { + // Скалярный placeholder. + if (is_array($a)) { + $error = $errmsg = "NOT_A_SCALAR_PLACEHOLDER_$key"; + break; + } + $repl = is_int($a) || is_float($a) ? str_replace(',', '.', $a) : "'".addslashes($a)."'"; + break; + } + // Иначе это массив или список. + if (is_object($a)) { + $a = get_object_vars($a); + } + + if (!is_array($a)) { + $error = $errmsg = "NOT_AN_ARRAY_PLACEHOLDER_$key"; + break; + } + if ($type === '@') { + // Это список. + foreach ($a as $v) { + if (is_null($v)) { + $r = "NULL"; + } else { + $r = "'".@addslashes($v)."'"; + } + + $repl .= ($repl===''? "" : ",").$r; + } + } elseif ($type === '%') { + // Это набор пар ключ=>значение. + $lerror = array(); + foreach ($a as $k=>$v) { + if (!is_string($k)) { + $lerror[$k] = "NOT_A_STRING_KEY_{$k}_FOR_PLACEHOLDER_$key"; + } else { + $k = preg_replace('/[^a-zA-Z0-9_]/', '_', $k); + } + + if (is_null($v)) { + $r = "=NULL"; + } else { + $r = "='".@addslashes($v)."'"; + } + + $repl .= ($repl===''? "" : ", ").$k.$r; + } + // Если была ошибка, составляем сообщение. + if (count($lerror)) { + $repl = ''; + foreach ($a as $k=>$v) { + if (isset($lerror[$k])) { + $repl .= ($repl===''? "" : ", ").$lerror[$k]; + } else { + $k = preg_replace('/[^a-zA-Z0-9_-]/', '_', $k); + $repl .= ($repl===''? "" : ", ").$k."=?"; + } + } + $error = $errmsg = $repl; + } + } + } while (false); + if ($errmsg) { + $compiled[$num]['error'] = $errmsg; + } + if (!$error) { + $out .= $repl; + } + } + $out .= substr($tmpl, $p); + + // Если возникла ошибка, переделываем результирующую строку + // в сообщение об ошибке (расставляем диагностические строки + // вместо ошибочных placeholder-ов). + if ($error) { + $out = ''; + $p = 0; // текущая позиция + foreach ($compiled as $num=>$e) { + list($key, $type, $start, $length) = $e; + $out .= substr($tmpl, $p, $start - $p); + $p = $start + $length; + if (isset($e['error'])) { + $out .= $e['error']; + } else { + $out .= substr($tmpl, $start, $length); + } + } + // Последняя часть строки. + $out .= substr($tmpl, $p); + $errormsg = $out; + return false; + } else { + $errormsg = false; + return $out; + } + } + + public function dump($filename) + { + $h = fopen($filename, 'w'); + $q = $this->placehold("SHOW FULL TABLES LIKE '__%';"); + $result = $this->mysqli->query($q); + while ($row = $result->fetch_row()) { + if ($row[1] == 'BASE TABLE') { + $this->dump_table($row[0], $h); + } + } + fclose($h); + } + + public function restore($filename) + { + $templine = ''; + $h = fopen($filename, 'r'); + + // Loop through each line + if ($h) { + while (!feof($h)) { + $line = fgets($h); + // Only continue if it's not a comment + if (substr($line, 0, 2) != '--' && $line != '') { + // Add this line to the current segment + $templine .= $line; + // If it has a semicolon at the end, it's the end of the query + if (substr(trim($line), -1, 1) == ';') { + // Perform the query + $this->query($templine) or print('Error performing query \''.$templine.'\': '.$this->mysqli->error.'

'); + // Reset temp variable to empty + $templine = ''; + } + } + } + } + fclose($h); + } + + + private function dump_table($table, $h) + { + $sql = "SELECT * FROM `$table`;"; + $result = $this->mysqli->query($sql); + if ($result) { + $table_no_prefix = preg_replace('/^('.$this->config->db_prefix.')/i', "__", $table); + fwrite($h, "/* Data for table $table_no_prefix */\n"); + fwrite($h, "TRUNCATE TABLE `$table_no_prefix`;\n"); + + $num_rows = $result->num_rows; + $num_fields = $this->mysqli->field_count; + + if ($num_rows > 0) { + $field_type=array(); + $field_name = array(); + $meta = $result->fetch_fields(); + foreach ($meta as $m) { + array_push($field_type, $m->type); + array_push($field_name, $m->name); + } + $fields = implode('`, `', $field_name); + fwrite($h, "INSERT INTO `$table_no_prefix` (`$fields`) VALUES\n"); + $index=0; + while ($row = $result->fetch_row()) { + fwrite($h, "("); + for ($i=0; $i < $num_fields; $i++) { + if (is_null($row[$i])) { + fwrite($h, "null"); + } else { + switch ($field_type[$i]) { + case 'int': + fwrite($h, $row[$i]); + break; + case 'string': + case 'blob' : + default: + fwrite($h, "'". $this->mysqli->real_escape_string($row[$i])."'"); + + } + } + if ($i < $num_fields-1) { + fwrite($h, ","); + } + } + fwrite($h, ")"); + + if ($index < $num_rows-1) { + fwrite($h, ","); + } else { + fwrite($h, ";"); + } + fwrite($h, "\n"); + + $index++; + } + } + $result->free(); + } + fwrite($h, "\n"); + } } - diff --git a/api/Delivery.php b/api/Delivery.php index b5650e9..ffbe52e 100755 --- a/api/Delivery.php +++ b/api/Delivery.php @@ -14,87 +14,88 @@ class Delivery extends Simpla { - public function get_delivery($id) - { - $query = $this->db->placehold("SELECT d.id, d.name, d.description, d.free_from, d.price, d.enabled, d.position, d.separate_payment + public function get_delivery($id) + { + $query = $this->db->placehold("SELECT d.id, d.name, d.description, d.free_from, d.price, d.enabled, d.position, d.separate_payment FROM __delivery d WHERE d.id=? LIMIT 1", intval($id)); - $this->db->query($query); - return $this->db->result(); - } + $this->db->query($query); + return $this->db->result(); + } - public function get_deliveries($filter = array()) - { - // По умолчанию - $enabled_filter = ''; + public function get_deliveries($filter = array()) + { + // По умолчанию + $enabled_filter = ''; - if(!empty($filter['enabled'])) - $enabled_filter = $this->db->placehold('AND d.enabled=?', intval($filter['enabled'])); + if (!empty($filter['enabled'])) { + $enabled_filter = $this->db->placehold('AND d.enabled=?', intval($filter['enabled'])); + } - $query = $this->db->placehold("SELECT d.id, d.name, d.description, d.free_from, d.price, d.enabled, d.position, d.separate_payment + $query = $this->db->placehold("SELECT d.id, d.name, d.description, d.free_from, d.price, d.enabled, d.position, d.separate_payment FROM __delivery d WHERE 1 $enabled_filter ORDER BY d.position"); - $this->db->query($query); + $this->db->query($query); - return $this->db->results(); - } + return $this->db->results(); + } - public function update_delivery($id, $delivery) - { - $query = $this->db->placehold("UPDATE __delivery SET ?% WHERE id in(?@)", $delivery, (array)$id); - $this->db->query($query); + public function update_delivery($id, $delivery) + { + $query = $this->db->placehold("UPDATE __delivery SET ?% WHERE id in(?@)", $delivery, (array)$id); + $this->db->query($query); - return $id; - } + return $id; + } - public function add_delivery($delivery) - { - $query = $this->db->placehold('INSERT INTO __delivery SET ?%', $delivery); + public function add_delivery($delivery) + { + $query = $this->db->placehold('INSERT INTO __delivery SET ?%', $delivery); - if(!$this->db->query($query)) - return false; + if (!$this->db->query($query)) { + return false; + } - $id = $this->db->insert_id(); - $this->db->query("UPDATE __delivery SET position=id WHERE id=?", intval($id)); + $id = $this->db->insert_id(); + $this->db->query("UPDATE __delivery SET position=id WHERE id=?", intval($id)); - return $id; - } + return $id; + } - public function delete_delivery($id) - { - if(!empty($id)) - { - // Удаляем связь метода доставки с оплатами - $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE delivery_id=?", intval($id)); - $this->db->query($query); + public function delete_delivery($id) + { + if (!empty($id)) { + // Удаляем связь метода доставки с оплатами + $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE delivery_id=?", intval($id)); + $this->db->query($query); - $query = $this->db->placehold("DELETE FROM __delivery WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - } + $query = $this->db->placehold("DELETE FROM __delivery WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + } + } - } + public function get_delivery_payments($id) + { + $query = $this->db->placehold("SELECT payment_method_id FROM __delivery_payment WHERE delivery_id=?", intval($id)); + $this->db->query($query); - public function get_delivery_payments($id) - { - $query = $this->db->placehold("SELECT payment_method_id FROM __delivery_payment WHERE delivery_id=?", intval($id)); - $this->db->query($query); - - return $this->db->results('payment_method_id'); - } - - public function update_delivery_payments($id, $payment_methods_ids) - { - $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE delivery_id=?", intval($id)); - $this->db->query($query); - if(is_array($payment_methods_ids)) - foreach($payment_methods_ids as $p_id) - $this->db->query("INSERT INTO __delivery_payment SET delivery_id=?, payment_method_id=?", $id, $p_id); - } + return $this->db->results('payment_method_id'); + } + public function update_delivery_payments($id, $payment_methods_ids) + { + $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE delivery_id=?", intval($id)); + $this->db->query($query); + if (is_array($payment_methods_ids)) { + foreach ($payment_methods_ids as $p_id) { + $this->db->query("INSERT INTO __delivery_payment SET delivery_id=?, payment_method_id=?", $id, $p_id); + } + } + } } diff --git a/api/Design.php b/api/Design.php index b77fd85..c5ba383 100755 --- a/api/Design.php +++ b/api/Design.php @@ -14,294 +14,310 @@ class Design extends Simpla { - public $smarty; - - public function __construct() - { - parent::__construct(); - - // Создаем и настраиваем Смарти - $this->smarty = new Smarty(); - $this->smarty->compile_check = $this->config->smarty_compile_check; - $this->smarty->caching = $this->config->smarty_caching; - $this->smarty->cache_lifetime = $this->config->smarty_cache_lifetime; - $this->smarty->debugging = $this->config->smarty_debugging; - $this->smarty->error_reporting = E_ALL & ~E_NOTICE; - - // Берем тему из настроек - $theme = $this->settings->theme; - - - $this->smarty->compile_dir = $this->config->root_dir.'/compiled/'.$theme; - $this->smarty->template_dir = $this->config->root_dir.'/design/'.$theme.'/html'; - - if(!is_dir($this->config->root_dir.'/compiled')) - mkdir($this->config->root_dir.'/compiled', 0777); - - // Создаем папку для скомпилированных шаблонов текущей темы - if(!is_dir($this->smarty->compile_dir)) - mkdir($this->smarty->compile_dir, 0777); - - $this->smarty->cache_dir = 'cache'; - - $this->smarty->registerPlugin('modifier', 'resize', array($this, 'resize_modifier')); - $this->smarty->registerPlugin('modifier', 'token', array($this, 'token_modifier')); - $this->smarty->registerPlugin('modifier', 'plural', array($this, 'plural_modifier')); - $this->smarty->registerPlugin('function', 'url', array($this, 'url_modifier')); - $this->smarty->registerPlugin('modifier', 'first', array($this, 'first_modifier')); - $this->smarty->registerPlugin('modifier', 'cut', array($this, 'cut_modifier')); - $this->smarty->registerPlugin('modifier', 'date', array($this, 'date_modifier')); - $this->smarty->registerPlugin('modifier', 'time', array($this, 'time_modifier')); - $this->smarty->registerPlugin('function', 'api', array($this, 'api_plugin')); - - if($this->config->smarty_html_minify) - $this->smarty->loadFilter('output', 'trimwhitespace'); - } - - public function assign($var, $value) - { - return $this->smarty->assign($var, $value); - } - - public function fetch($template) - { - // Передаем в дизайн то, что может понадобиться в нем - $this->assign('config', $this->config); - $this->assign('settings', $this->settings); - return $this->smarty->fetch($template); - } - - public function set_templates_dir($dir) - { - $this->smarty->template_dir = $dir; - } - - public function set_compiled_dir($dir) - { - $this->smarty->compile_dir = $dir; - } - - public function get_var($name) - { - return $this->smarty->getTemplateVars($name); - } - - public function clear_cache() - { - $this->smarty->clearAllCache(); - } - - private function is_mobile_browser() - { - $user_agent = $_SERVER['HTTP_USER_AGENT']; - $http_accept = isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:''; - - if(eregi('iPad', $user_agent)) - return false; - - if(stristr($user_agent, 'windows') && !stristr($user_agent, 'windows ce')) - return false; - - if(eregi('windows ce|iemobile|mobile|symbian|mini|wap|pda|psp|up.browser|up.link|mmp|midp|phone|pocket', $user_agent)) - return true; - - if(stristr($http_accept, 'text/vnd.wap.wml') || stristr($http_accept, 'application/vnd.wap.xhtml+xml')) - return true; - - if(!empty($_SERVER['HTTP_X_WAP_PROFILE']) || !empty($_SERVER['HTTP_PROFILE']) || !empty($_SERVER['X-OperaMini-Features']) || !empty($_SERVER['UA-pixels'])) - return true; - - $agents = array( - 'acs-'=>'acs-', - 'alav'=>'alav', - 'alca'=>'alca', - 'amoi'=>'amoi', - 'audi'=>'audi', - 'aste'=>'aste', - 'avan'=>'avan', - 'benq'=>'benq', - 'bird'=>'bird', - 'blac'=>'blac', - 'blaz'=>'blaz', - 'brew'=>'brew', - 'cell'=>'cell', - 'cldc'=>'cldc', - 'cmd-'=>'cmd-', - 'dang'=>'dang', - 'doco'=>'doco', - 'eric'=>'eric', - 'hipt'=>'hipt', - 'inno'=>'inno', - 'ipaq'=>'ipaq', - 'java'=>'java', - 'jigs'=>'jigs', - 'kddi'=>'kddi', - 'keji'=>'keji', - 'leno'=>'leno', - 'lg-c'=>'lg-c', - 'lg-d'=>'lg-d', - 'lg-g'=>'lg-g', - 'lge-'=>'lge-', - 'maui'=>'maui', - 'maxo'=>'maxo', - 'midp'=>'midp', - 'mits'=>'mits', - 'mmef'=>'mmef', - 'mobi'=>'mobi', - 'mot-'=>'mot-', - 'moto'=>'moto', - 'mwbp'=>'mwbp', - 'nec-'=>'nec-', - 'newt'=>'newt', - 'noki'=>'noki', - 'opwv'=>'opwv', - 'palm'=>'palm', - 'pana'=>'pana', - 'pant'=>'pant', - 'pdxg'=>'pdxg', - 'phil'=>'phil', - 'play'=>'play', - 'pluc'=>'pluc', - 'port'=>'port', - 'prox'=>'prox', - 'qtek'=>'qtek', - 'qwap'=>'qwap', - 'sage'=>'sage', - 'sams'=>'sams', - 'sany'=>'sany', - 'sch-'=>'sch-', - 'sec-'=>'sec-', - 'send'=>'send', - 'seri'=>'seri', - 'sgh-'=>'sgh-', - 'shar'=>'shar', - 'sie-'=>'sie-', - 'siem'=>'siem', - 'smal'=>'smal', - 'smar'=>'smar', - 'sony'=>'sony', - 'sph-'=>'sph-', - 'symb'=>'symb', - 't-mo'=>'t-mo', - 'teli'=>'teli', - 'tim-'=>'tim-', - 'tosh'=>'tosh', - 'treo'=>'treo', - 'tsm-'=>'tsm-', - 'upg1'=>'upg1', - 'upsi'=>'upsi', - 'vk-v'=>'vk-v', - 'voda'=>'voda', - 'wap-'=>'wap-', - 'wapa'=>'wapa', - 'wapi'=>'wapi', - 'wapp'=>'wapp', - 'wapr'=>'wapr', - 'webc'=>'webc', - 'winw'=>'winw', - 'winw'=>'winw', - 'xda-'=>'xda-' - ); - - if(!empty($agents[substr($_SERVER['HTTP_USER_AGENT'], 0, 4)])) - return true; - } - - - public function resize_modifier($filename, $width=0, $height=0, $set_watermark=false) - { - $resized_filename = $this->image->add_resize_params($filename, $width, $height, $set_watermark); - $resized_filename_encoded = $resized_filename; - - if(substr($resized_filename_encoded, 0, 7) == 'http://') - $resized_filename_encoded = rawurlencode($resized_filename_encoded); - - $resized_filename_encoded = rawurlencode($resized_filename_encoded); - - return $this->config->root_url.'/'.$this->config->resized_images_dir.$resized_filename_encoded.'?'.$this->config->token($resized_filename); - } - - public function token_modifier($text) - { - return $this->config->token($text); - } - - public function url_modifier($params) - { - if(is_array(reset($params))) - return $this->request->url(reset($params)); - else - return $this->request->url($params); - } - - public function plural_modifier($number, $singular, $plural1, $plural2=null) - { - $number = abs($number); - if(!empty($plural2)) - { - $p1 = $number%10; - $p2 = $number%100; - if($number == 0) - return $plural1; - if($p1==1 && !($p2>=11 && $p2<=19)) - return $singular; - elseif($p1>=2 && $p1<=4 && !($p2>=11 && $p2<=19)) - return $plural2; - else - return $plural1; - }else - { - if($number == 1) - return $singular; - else - return $plural1; - } - - } - - public function first_modifier($params = array()) - { - if(!is_array($params)) - return false; - return reset($params); - } - - public function cut_modifier($array, $num=1) - { - if($num>=0) - return array_slice($array, $num, count($array)-$num, true); - else - return array_slice($array, 0, count($array)+$num, true); - } - - public function date_modifier($date, $format = null) - { - if(empty($date)) - $date = date("Y-m-d"); - return date(empty($format)?$this->settings->date_format:$format, strtotime($date)); - } - - public function time_modifier($date, $format = null) - { - return date(empty($format)?'H:i':$format, strtotime($date)); - } - - public function api_plugin($params, &$smarty) - { - if(!isset($params['module']) || !isset($params['method'])) - return false; - - $module = $params['module']; - $method = $params['method']; - $var = $params['var']; - unset($params['module']); - unset($params['method']); - unset($params['var']); - - if(isset($params['_'])) - $res = $this->$module->$method($params['_']); - else - $res = $this->$module->$method($params); - $smarty->assign($var, $res); - } + public $smarty; + + public function __construct() + { + parent::__construct(); + + // Создаем и настраиваем Смарти + $this->smarty = new Smarty(); + $this->smarty->compile_check = $this->config->smarty_compile_check; + $this->smarty->caching = $this->config->smarty_caching; + $this->smarty->cache_lifetime = $this->config->smarty_cache_lifetime; + $this->smarty->debugging = $this->config->smarty_debugging; + $this->smarty->error_reporting = E_ALL & ~E_NOTICE; + + // Берем тему из настроек + $theme = $this->settings->theme; + + + $this->smarty->compile_dir = $this->config->root_dir.'/compiled/'.$theme; + $this->smarty->template_dir = $this->config->root_dir.'/design/'.$theme.'/html'; + + if (!is_dir($this->config->root_dir.'/compiled')) { + mkdir($this->config->root_dir.'/compiled', 0777); + } + + // Создаем папку для скомпилированных шаблонов текущей темы + if (!is_dir($this->smarty->compile_dir)) { + mkdir($this->smarty->compile_dir, 0777); + } + + $this->smarty->cache_dir = 'cache'; + + $this->smarty->registerPlugin('modifier', 'resize', array($this, 'resize_modifier')); + $this->smarty->registerPlugin('modifier', 'token', array($this, 'token_modifier')); + $this->smarty->registerPlugin('modifier', 'plural', array($this, 'plural_modifier')); + $this->smarty->registerPlugin('function', 'url', array($this, 'url_modifier')); + $this->smarty->registerPlugin('modifier', 'first', array($this, 'first_modifier')); + $this->smarty->registerPlugin('modifier', 'cut', array($this, 'cut_modifier')); + $this->smarty->registerPlugin('modifier', 'date', array($this, 'date_modifier')); + $this->smarty->registerPlugin('modifier', 'time', array($this, 'time_modifier')); + $this->smarty->registerPlugin('function', 'api', array($this, 'api_plugin')); + + if ($this->config->smarty_html_minify) { + $this->smarty->loadFilter('output', 'trimwhitespace'); + } + } + + public function assign($var, $value) + { + return $this->smarty->assign($var, $value); + } + + public function fetch($template) + { + // Передаем в дизайн то, что может понадобиться в нем + $this->assign('config', $this->config); + $this->assign('settings', $this->settings); + return $this->smarty->fetch($template); + } + + public function set_templates_dir($dir) + { + $this->smarty->template_dir = $dir; + } + + public function set_compiled_dir($dir) + { + $this->smarty->compile_dir = $dir; + } + + public function get_var($name) + { + return $this->smarty->getTemplateVars($name); + } + + public function clear_cache() + { + $this->smarty->clearAllCache(); + } + + private function is_mobile_browser() + { + $user_agent = $_SERVER['HTTP_USER_AGENT']; + $http_accept = isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:''; + + if (eregi('iPad', $user_agent)) { + return false; + } + + if (stristr($user_agent, 'windows') && !stristr($user_agent, 'windows ce')) { + return false; + } + + if (eregi('windows ce|iemobile|mobile|symbian|mini|wap|pda|psp|up.browser|up.link|mmp|midp|phone|pocket', $user_agent)) { + return true; + } + + if (stristr($http_accept, 'text/vnd.wap.wml') || stristr($http_accept, 'application/vnd.wap.xhtml+xml')) { + return true; + } + + if (!empty($_SERVER['HTTP_X_WAP_PROFILE']) || !empty($_SERVER['HTTP_PROFILE']) || !empty($_SERVER['X-OperaMini-Features']) || !empty($_SERVER['UA-pixels'])) { + return true; + } + + $agents = array( + 'acs-'=>'acs-', + 'alav'=>'alav', + 'alca'=>'alca', + 'amoi'=>'amoi', + 'audi'=>'audi', + 'aste'=>'aste', + 'avan'=>'avan', + 'benq'=>'benq', + 'bird'=>'bird', + 'blac'=>'blac', + 'blaz'=>'blaz', + 'brew'=>'brew', + 'cell'=>'cell', + 'cldc'=>'cldc', + 'cmd-'=>'cmd-', + 'dang'=>'dang', + 'doco'=>'doco', + 'eric'=>'eric', + 'hipt'=>'hipt', + 'inno'=>'inno', + 'ipaq'=>'ipaq', + 'java'=>'java', + 'jigs'=>'jigs', + 'kddi'=>'kddi', + 'keji'=>'keji', + 'leno'=>'leno', + 'lg-c'=>'lg-c', + 'lg-d'=>'lg-d', + 'lg-g'=>'lg-g', + 'lge-'=>'lge-', + 'maui'=>'maui', + 'maxo'=>'maxo', + 'midp'=>'midp', + 'mits'=>'mits', + 'mmef'=>'mmef', + 'mobi'=>'mobi', + 'mot-'=>'mot-', + 'moto'=>'moto', + 'mwbp'=>'mwbp', + 'nec-'=>'nec-', + 'newt'=>'newt', + 'noki'=>'noki', + 'opwv'=>'opwv', + 'palm'=>'palm', + 'pana'=>'pana', + 'pant'=>'pant', + 'pdxg'=>'pdxg', + 'phil'=>'phil', + 'play'=>'play', + 'pluc'=>'pluc', + 'port'=>'port', + 'prox'=>'prox', + 'qtek'=>'qtek', + 'qwap'=>'qwap', + 'sage'=>'sage', + 'sams'=>'sams', + 'sany'=>'sany', + 'sch-'=>'sch-', + 'sec-'=>'sec-', + 'send'=>'send', + 'seri'=>'seri', + 'sgh-'=>'sgh-', + 'shar'=>'shar', + 'sie-'=>'sie-', + 'siem'=>'siem', + 'smal'=>'smal', + 'smar'=>'smar', + 'sony'=>'sony', + 'sph-'=>'sph-', + 'symb'=>'symb', + 't-mo'=>'t-mo', + 'teli'=>'teli', + 'tim-'=>'tim-', + 'tosh'=>'tosh', + 'treo'=>'treo', + 'tsm-'=>'tsm-', + 'upg1'=>'upg1', + 'upsi'=>'upsi', + 'vk-v'=>'vk-v', + 'voda'=>'voda', + 'wap-'=>'wap-', + 'wapa'=>'wapa', + 'wapi'=>'wapi', + 'wapp'=>'wapp', + 'wapr'=>'wapr', + 'webc'=>'webc', + 'winw'=>'winw', + 'winw'=>'winw', + 'xda-'=>'xda-' + ); + + if (!empty($agents[substr($_SERVER['HTTP_USER_AGENT'], 0, 4)])) { + return true; + } + } + + + public function resize_modifier($filename, $width=0, $height=0, $set_watermark=false) + { + $resized_filename = $this->image->add_resize_params($filename, $width, $height, $set_watermark); + $resized_filename_encoded = $resized_filename; + + if (substr($resized_filename_encoded, 0, 7) == 'http://') { + $resized_filename_encoded = rawurlencode($resized_filename_encoded); + } + + $resized_filename_encoded = rawurlencode($resized_filename_encoded); + + return $this->config->root_url.'/'.$this->config->resized_images_dir.$resized_filename_encoded.'?'.$this->config->token($resized_filename); + } + + public function token_modifier($text) + { + return $this->config->token($text); + } + + public function url_modifier($params) + { + if (is_array(reset($params))) { + return $this->request->url(reset($params)); + } else { + return $this->request->url($params); + } + } + + public function plural_modifier($number, $singular, $plural1, $plural2=null) + { + $number = abs($number); + if (!empty($plural2)) { + $p1 = $number%10; + $p2 = $number%100; + if ($number == 0) { + return $plural1; + } + if ($p1==1 && !($p2>=11 && $p2<=19)) { + return $singular; + } elseif ($p1>=2 && $p1<=4 && !($p2>=11 && $p2<=19)) { + return $plural2; + } else { + return $plural1; + } + } else { + if ($number == 1) { + return $singular; + } else { + return $plural1; + } + } + } + + public function first_modifier($params = array()) + { + if (!is_array($params)) { + return false; + } + return reset($params); + } + + public function cut_modifier($array, $num=1) + { + if ($num>=0) { + return array_slice($array, $num, count($array)-$num, true); + } else { + return array_slice($array, 0, count($array)+$num, true); + } + } + + public function date_modifier($date, $format = null) + { + if (empty($date)) { + $date = date("Y-m-d"); + } + return date(empty($format)?$this->settings->date_format:$format, strtotime($date)); + } + + public function time_modifier($date, $format = null) + { + return date(empty($format)?'H:i':$format, strtotime($date)); + } + + public function api_plugin($params, &$smarty) + { + if (!isset($params['module']) || !isset($params['method'])) { + return false; + } + + $module = $params['module']; + $method = $params['method']; + $var = $params['var']; + unset($params['module']); + unset($params['method']); + unset($params['var']); + + if (isset($params['_'])) { + $res = $this->$module->$method($params['_']); + } else { + $res = $this->$module->$method($params); + } + $smarty->assign($var, $res); + } } diff --git a/api/Features.php b/api/Features.php index 01ef55b..6545ece 100755 --- a/api/Features.php +++ b/api/Features.php @@ -14,183 +14,192 @@ class Features extends Simpla { - public function get_features($filter = array()) - { - $category_id_filter = ''; - if(isset($filter['category_id'])) - $category_id_filter = $this->db->placehold('AND id in(SELECT feature_id FROM __categories_features AS cf WHERE cf.category_id in(?@))', (array)$filter['category_id']); - - $in_filter_filter = ''; - if(isset($filter['in_filter'])) - $in_filter_filter = $this->db->placehold('AND f.in_filter=?', intval($filter['in_filter'])); - - $id_filter = ''; - if(!empty($filter['id'])) - $id_filter = $this->db->placehold('AND f.id in(?@)', (array)$filter['id']); - - // Выбираем свойства - $query = $this->db->placehold("SELECT f.id, f.name, f.position, f.in_filter + public function get_features($filter = array()) + { + $category_id_filter = ''; + if (isset($filter['category_id'])) { + $category_id_filter = $this->db->placehold('AND id in(SELECT feature_id FROM __categories_features AS cf WHERE cf.category_id in(?@))', (array)$filter['category_id']); + } + + $in_filter_filter = ''; + if (isset($filter['in_filter'])) { + $in_filter_filter = $this->db->placehold('AND f.in_filter=?', intval($filter['in_filter'])); + } + + $id_filter = ''; + if (!empty($filter['id'])) { + $id_filter = $this->db->placehold('AND f.id in(?@)', (array)$filter['id']); + } + + // Выбираем свойства + $query = $this->db->placehold("SELECT f.id, f.name, f.position, f.in_filter FROM __features AS f WHERE 1 $category_id_filter $in_filter_filter $id_filter ORDER BY f.position"); - $this->db->query($query); - return $this->db->results(); - } - - public function get_feature($id) - { - // Выбираем свойство - $query = $this->db->placehold("SELECT f.id, f.name, f.position, f.in_filter + $this->db->query($query); + return $this->db->results(); + } + + public function get_feature($id) + { + // Выбираем свойство + $query = $this->db->placehold("SELECT f.id, f.name, f.position, f.in_filter FROM __features AS f WHERE f.id=? LIMIT 1", $id); - $this->db->query($query); - return $this->db->result(); - } + $this->db->query($query); + return $this->db->result(); + } - public function get_feature_categories($id) - { - $query = $this->db->placehold("SELECT cf.category_id as category_id + public function get_feature_categories($id) + { + $query = $this->db->placehold("SELECT cf.category_id as category_id FROM __categories_features cf WHERE cf.feature_id = ?", $id); - $this->db->query($query); - return $this->db->results('category_id'); - } - - public function add_feature($feature) - { - $query = $this->db->placehold("INSERT INTO __features SET ?%", $feature); - $this->db->query($query); - $id = $this->db->insert_id(); - $query = $this->db->placehold("UPDATE __features SET position=id WHERE id=? LIMIT 1", $id); - $this->db->query($query); - return $id; - } - - public function update_feature($id, $feature) - { - $query = $this->db->placehold("UPDATE __features SET ?% WHERE id in(?@) LIMIT ?", (array)$feature, (array)$id, count((array)$id)); - $this->db->query($query); - return $id; - } - - public function delete_feature($id = array()) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __features WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - $query = $this->db->placehold("DELETE FROM __options WHERE feature_id=?", intval($id)); - $this->db->query($query); - $query = $this->db->placehold("DELETE FROM __categories_features WHERE feature_id=?", intval($id)); - $this->db->query($query); - } - } - - - public function delete_option($product_id, $feature_id) - { - $query = $this->db->placehold("DELETE FROM __options WHERE product_id=? AND feature_id=? LIMIT 1", intval($product_id), intval($feature_id)); - $this->db->query($query); - } - - - public function update_option($product_id, $feature_id, $value) - { - if($value != '') - $query = $this->db->placehold("REPLACE INTO __options SET value=?, product_id=?, feature_id=?", $value, intval($product_id), intval($feature_id)); - else - $query = $this->db->placehold("DELETE FROM __options WHERE feature_id=? AND product_id=?", intval($feature_id), intval($product_id)); - return $this->db->query($query); - } - - - public function add_feature_category($id, $category_id) - { - $query = $this->db->placehold("INSERT IGNORE INTO __categories_features SET feature_id=?, category_id=?", $id, $category_id); - $this->db->query($query); - } - - public function update_feature_categories($id, $categories) - { - $id = intval($id); - $query = $this->db->placehold("DELETE FROM __categories_features WHERE feature_id=?", $id); - $this->db->query($query); - - - if(is_array($categories)) - { - $values = array(); - foreach($categories as $category) - $values[] = "($id , ".intval($category).")"; - - $query = $this->db->placehold("INSERT INTO __categories_features (feature_id, category_id) VALUES ".implode(', ', $values)); - $this->db->query($query); - - // Удалим значения из options - $query = $this->db->placehold("DELETE o + $this->db->query($query); + return $this->db->results('category_id'); + } + + public function add_feature($feature) + { + $query = $this->db->placehold("INSERT INTO __features SET ?%", $feature); + $this->db->query($query); + $id = $this->db->insert_id(); + $query = $this->db->placehold("UPDATE __features SET position=id WHERE id=? LIMIT 1", $id); + $this->db->query($query); + return $id; + } + + public function update_feature($id, $feature) + { + $query = $this->db->placehold("UPDATE __features SET ?% WHERE id in(?@) LIMIT ?", (array)$feature, (array)$id, count((array)$id)); + $this->db->query($query); + return $id; + } + + public function delete_feature($id = array()) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __features WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + $query = $this->db->placehold("DELETE FROM __options WHERE feature_id=?", intval($id)); + $this->db->query($query); + $query = $this->db->placehold("DELETE FROM __categories_features WHERE feature_id=?", intval($id)); + $this->db->query($query); + } + } + + + public function delete_option($product_id, $feature_id) + { + $query = $this->db->placehold("DELETE FROM __options WHERE product_id=? AND feature_id=? LIMIT 1", intval($product_id), intval($feature_id)); + $this->db->query($query); + } + + + public function update_option($product_id, $feature_id, $value) + { + if ($value != '') { + $query = $this->db->placehold("REPLACE INTO __options SET value=?, product_id=?, feature_id=?", $value, intval($product_id), intval($feature_id)); + } else { + $query = $this->db->placehold("DELETE FROM __options WHERE feature_id=? AND product_id=?", intval($feature_id), intval($product_id)); + } + return $this->db->query($query); + } + + + public function add_feature_category($id, $category_id) + { + $query = $this->db->placehold("INSERT IGNORE INTO __categories_features SET feature_id=?, category_id=?", $id, $category_id); + $this->db->query($query); + } + + public function update_feature_categories($id, $categories) + { + $id = intval($id); + $query = $this->db->placehold("DELETE FROM __categories_features WHERE feature_id=?", $id); + $this->db->query($query); + + + if (is_array($categories)) { + $values = array(); + foreach ($categories as $category) { + $values[] = "($id , ".intval($category).")"; + } + + $query = $this->db->placehold("INSERT INTO __categories_features (feature_id, category_id) VALUES ".implode(', ', $values)); + $this->db->query($query); + + // Удалим значения из options + $query = $this->db->placehold("DELETE o FROM __options o LEFT JOIN __products_categories pc ON pc.product_id=o.product_id WHERE o.feature_id=? AND pc.position=(SELECT MIN(pc2.position) FROM __products_categories pc2 WHERE pc.product_id=pc2.product_id) AND pc.category_id not in(?@)", $id, $categories); - $this->db->query($query); - } - else - { - // Удалим значения из options - $query = $this->db->placehold("DELETE o FROM __options o WHERE o.feature_id=?", $id); - $this->db->query($query); - } - } - - - public function get_options($filter = array()) - { - $feature_id_filter = ''; - $product_id_filter = ''; - $category_id_filter = ''; - $visible_filter = ''; - $in_stock_filter = ''; - $brand_id_filter = ''; - $features_filter = ''; - - if(empty($filter['feature_id']) && empty($filter['product_id'])) - return array(); - - $group_by = ''; - if(isset($filter['feature_id'])) - $group_by = 'GROUP BY feature_id, value'; - - if(isset($filter['feature_id'])) - $feature_id_filter = $this->db->placehold('AND po.feature_id in(?@)', (array)$filter['feature_id']); - - if(isset($filter['product_id'])) - $product_id_filter = $this->db->placehold('AND po.product_id in(?@)', (array)$filter['product_id']); - - if(isset($filter['category_id'])) - $category_id_filter = $this->db->placehold('INNER JOIN __products_categories pc ON pc.product_id=po.product_id AND pc.category_id in(?@)', (array)$filter['category_id']); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('INNER JOIN __products p ON p.id=po.product_id AND p.visible=?', intval($filter['visible'])); - - if(isset($filter['in_stock'])) - $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=po.product_id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); - - if(isset($filter['brand_id'])) - $brand_id_filter = $this->db->placehold('AND po.product_id in(SELECT id FROM __products WHERE brand_id in(?@))', (array)$filter['brand_id']); - - if(isset($filter['features'])) - foreach($filter['features'] as $feature=>$value) - { - $features_filter .= $this->db->placehold('AND (po.feature_id=? OR po.product_id in (SELECT product_id FROM __options WHERE feature_id=? AND value=? )) ', $feature, $feature, $value); - } - - - $query = $this->db->placehold("SELECT po.feature_id, po.value, count(po.product_id) as count + $this->db->query($query); + } else { + // Удалим значения из options + $query = $this->db->placehold("DELETE o FROM __options o WHERE o.feature_id=?", $id); + $this->db->query($query); + } + } + + + public function get_options($filter = array()) + { + $feature_id_filter = ''; + $product_id_filter = ''; + $category_id_filter = ''; + $visible_filter = ''; + $in_stock_filter = ''; + $brand_id_filter = ''; + $features_filter = ''; + + if (empty($filter['feature_id']) && empty($filter['product_id'])) { + return array(); + } + + $group_by = ''; + if (isset($filter['feature_id'])) { + $group_by = 'GROUP BY feature_id, value'; + } + + if (isset($filter['feature_id'])) { + $feature_id_filter = $this->db->placehold('AND po.feature_id in(?@)', (array)$filter['feature_id']); + } + + if (isset($filter['product_id'])) { + $product_id_filter = $this->db->placehold('AND po.product_id in(?@)', (array)$filter['product_id']); + } + + if (isset($filter['category_id'])) { + $category_id_filter = $this->db->placehold('INNER JOIN __products_categories pc ON pc.product_id=po.product_id AND pc.category_id in(?@)', (array)$filter['category_id']); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('INNER JOIN __products p ON p.id=po.product_id AND p.visible=?', intval($filter['visible'])); + } + + if (isset($filter['in_stock'])) { + $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=po.product_id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); + } + + if (isset($filter['brand_id'])) { + $brand_id_filter = $this->db->placehold('AND po.product_id in(SELECT id FROM __products WHERE brand_id in(?@))', (array)$filter['brand_id']); + } + + if (isset($filter['features'])) { + foreach ($filter['features'] as $feature=>$value) { + $features_filter .= $this->db->placehold('AND (po.feature_id=? OR po.product_id in (SELECT product_id FROM __options WHERE feature_id=? AND value=? )) ', $feature, $feature, $value); + } + } + + + $query = $this->db->placehold("SELECT po.feature_id, po.value, count(po.product_id) as count FROM __options po $visible_filter $category_id_filter @@ -203,19 +212,19 @@ public function get_options($filter = array()) GROUP BY po.feature_id, po.value ORDER BY po.value=0, -po.value DESC, po.value"); - $this->db->query($query); - return $this->db->results(); - } + $this->db->query($query); + return $this->db->results(); + } - public function get_product_options($product_id) - { - $query = $this->db->placehold("SELECT f.id as feature_id, f.name, po.value, po.product_id + public function get_product_options($product_id) + { + $query = $this->db->placehold("SELECT f.id as feature_id, f.name, po.value, po.product_id FROM __options po LEFT JOIN __features f ON f.id=po.feature_id WHERE po.product_id in(?@) ORDER BY f.position", (array)$product_id); - $this->db->query($query); - return $this->db->results(); - } + $this->db->query($query); + return $this->db->results(); + } } diff --git a/api/Feedbacks.php b/api/Feedbacks.php index a2bcebc..3eb1c20 100755 --- a/api/Feedbacks.php +++ b/api/Feedbacks.php @@ -15,106 +15,108 @@ class Feedbacks extends Simpla { - public function get_feedback($id) - { - $query = $this->db->placehold("SELECT f.id, f.name, f.email, f.ip, f.message, f.date FROM __feedbacks f WHERE id=? LIMIT 1", intval($id)); - - if($this->db->query($query)) - return $this->db->result(); - else - return false; - } - - public function get_feedbacks($filter = array(), $new_on_top = false) - { - // По умолчанию - $limit = 0; - $page = 1; - $keyword_filter = ''; - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND f.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.message LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.email LIKE "%'.$this->db->escape(trim($keyword)).'%" '); - } - - if($new_on_top) - $sort='DESC'; - else - $sort='ASC'; - - $query = $this->db->placehold("SELECT f.id, f.name, f.email, f.ip, f.message, f.date + public function get_feedback($id) + { + $query = $this->db->placehold("SELECT f.id, f.name, f.email, f.ip, f.message, f.date FROM __feedbacks f WHERE id=? LIMIT 1", intval($id)); + + if ($this->db->query($query)) { + return $this->db->result(); + } else { + return false; + } + } + + public function get_feedbacks($filter = array(), $new_on_top = false) + { + // По умолчанию + $limit = 0; + $page = 1; + $keyword_filter = ''; + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND f.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.message LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.email LIKE "%'.$this->db->escape(trim($keyword)).'%" '); + } + } + + if ($new_on_top) { + $sort='DESC'; + } else { + $sort='ASC'; + } + + $query = $this->db->placehold("SELECT f.id, f.name, f.email, f.ip, f.message, f.date FROM __feedbacks f WHERE 1 $keyword_filter ORDER BY f.id $sort $sql_limit"); - $this->db->query($query); - return $this->db->results(); - } + $this->db->query($query); + return $this->db->results(); + } - public function count_feedbacks($filter = array()) - { - $keyword_filter = ''; + public function count_feedbacks($filter = array()) + { + $keyword_filter = ''; - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND f.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.message LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.email LIKE "%'.$this->db->escape(trim($keyword)).'%" '); - } + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND f.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.message LIKE "%'.$this->db->escape(trim($keyword)).'%" OR f.email LIKE "%'.$this->db->escape(trim($keyword)).'%" '); + } + } - $query = $this->db->placehold("SELECT count(distinct f.id) as count + $query = $this->db->placehold("SELECT count(distinct f.id) as count FROM __feedbacks f WHERE 1 $keyword_filter"); - $this->db->query($query); - return $this->db->result('count'); + $this->db->query($query); + return $this->db->result('count'); + } - } - - public function add_feedback($feedback) - { - $query = $this->db->placehold('INSERT INTO __feedbacks + public function add_feedback($feedback) + { + $query = $this->db->placehold('INSERT INTO __feedbacks SET ?%, date = NOW()', - $feedback); - - if(!$this->db->query($query)) - return false; - - $id = $this->db->insert_id(); - return $id; - } - - - public function update_feedback($id, $feedback) - { - $date_query = ''; - if(isset($feedback->date)) - { - $date = $feedback->date; - unset($feedback->date); - $date_query = $this->db->placehold(', date=STR_TO_DATE(?, ?)', $date, $this->settings->date_format); - } - $query = $this->db->placehold("UPDATE __feedbacks SET ?% $date_query WHERE id in(?@) LIMIT 1", $feedback, (array)$id); - $this->db->query($query); - return $id; - } - - - public function delete_feedback($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __feedbacks WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - } - } + $feedback); + + if (!$this->db->query($query)) { + return false; + } + + $id = $this->db->insert_id(); + return $id; + } + + + public function update_feedback($id, $feedback) + { + $date_query = ''; + if (isset($feedback->date)) { + $date = $feedback->date; + unset($feedback->date); + $date_query = $this->db->placehold(', date=STR_TO_DATE(?, ?)', $date, $this->settings->date_format); + } + $query = $this->db->placehold("UPDATE __feedbacks SET ?% $date_query WHERE id in(?@) LIMIT 1", $feedback, (array)$id); + $this->db->query($query); + return $id; + } + + + public function delete_feedback($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __feedbacks WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + } + } } diff --git a/api/Image.php b/api/Image.php index ff68471..0222238 100755 --- a/api/Image.php +++ b/api/Image.php @@ -14,450 +14,459 @@ class Image extends Simpla { - private $allowed_extentions = array('png', 'gif', 'jpg', 'jpeg', 'ico'); - - public function __construct() - { - parent::__construct(); - } - - - /** - * Создание превью изображения - * @param $filename файл с изображением (без пути к файлу) - * @param max_w максимальная ширина - * @param max_h максимальная высота - * @return $string имя файла превью - */ - public function resize($filename) - { - list($source_file, $width , $height, $set_watermark) = $this->get_resize_params($filename); - - // Если вайл удаленный (http://), зальем его себе - if(substr($source_file, 0, 7) == 'http://') - { - // Имя оригинального файла - if(!$original_file = $this->download_image($source_file)) - return false; - - $resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark); - } - else - { - $original_file = $source_file; - } - - $resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark); - - - // Пути к папкам с картинками - $originals_dir = $this->config->root_dir.$this->config->original_images_dir; - $preview_dir = $this->config->root_dir.$this->config->resized_images_dir; - - $watermark_offet_x = $this->settings->watermark_offset_x; - $watermark_offet_y = $this->settings->watermark_offset_y; - - $sharpen = min(100, $this->settings->images_sharpen)/100; - $watermark_transparency = 1-min(100, $this->settings->watermark_transparency)/100; - - - if($set_watermark && is_file($this->config->root_dir.$this->config->watermark_file)) - $watermark = $this->config->root_dir.$this->config->watermark_file; - else - $watermark = null; - - if(class_exists('Imagick') && $this->config->use_imagick) - $this->image_constrain_imagick($originals_dir.$original_file, $preview_dir.$resized_file, $width, $height, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_transparency, $sharpen); - else - $this->image_constrain_gd($originals_dir.$original_file, $preview_dir.$resized_file, $width, $height, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_transparency); - - return $preview_dir.$resized_file; - } - - public function add_resize_params($filename, $width=0, $height=0, $set_watermark=false) - { - if('.' != ($dirname = pathinfo($filename, PATHINFO_DIRNAME))) - $file = $dirname.'/'.pathinfo($filename, PATHINFO_FILENAME); - else - $file = pathinfo($filename, PATHINFO_FILENAME); - $ext = pathinfo($filename, PATHINFO_EXTENSION); - - if($width>0 || $height>0) - $resized_filename = $file.'.'.($width>0?$width:'').'x'.($height>0?$height:'').($set_watermark?'w':'').'.'.$ext; - else - $resized_filename = $file.'.'.($set_watermark?'w.':'').$ext; - - return $resized_filename; - } - - public function get_resize_params($filename) - { - // Определаяем параметры ресайза - if(!preg_match('/(.+)\.([0-9]*)x([0-9]*)(w)?\.([^\.]+)$/', $filename, $matches)) - return false; - - $file = $matches[1]; // имя запрашиваемого файла - $width = $matches[2]; // ширина будущего изображения - $height = $matches[3]; // высота будущего изображения - $set_watermark = $matches[4] == 'w'; // ставить ли водяной знак - $ext = $matches[5]; // расширение файла - - return array($file.'.'.$ext, $width, $height, $set_watermark); - } - - - public function download_image($filename) - { - // Заливаем только есть такой файл есть в базе - $this->db->query('SELECT 1 FROM __images WHERE filename=? LIMIT 1', $filename); - if(!$this->db->result()) - return false; - - // Имя оригинального файла - $basename = explode('&', pathinfo($filename, PATHINFO_BASENAME)); - $uploaded_file = array_shift($basename); - $base = urldecode(pathinfo($uploaded_file, PATHINFO_FILENAME)); - $ext = pathinfo($uploaded_file, PATHINFO_EXTENSION); - - // Если такой файл существует, нужно придумать другое название - $new_name = urldecode($uploaded_file); - - while(file_exists($this->config->root_dir.$this->config->original_images_dir.$new_name)) - { - $new_base = pathinfo($new_name, PATHINFO_FILENAME); - if(preg_match('/_([0-9]+)$/', $new_base, $parts)) - $new_name = $base.'_'.($parts[1]+1).'.'.$ext; - else - $new_name = $base.'_1.'.$ext; - } - $this->db->query('UPDATE __images SET filename=? WHERE filename=?', $new_name, $filename); - - // Перед долгим копированием займем это имя - fclose(fopen($this->config->root_dir.$this->config->original_images_dir.$new_name, 'w')); - copy($filename, $this->config->root_dir.$this->config->original_images_dir.$new_name); - return $new_name; - } - - public function upload_image($filename, $name) - { - // Имя оригинального файла - $name = $this->correct_filename($name); - $uploaded_file = $new_name = pathinfo($name, PATHINFO_BASENAME); - $base = pathinfo($uploaded_file, PATHINFO_FILENAME); - $ext = pathinfo($uploaded_file, PATHINFO_EXTENSION); - - if(in_array(strtolower($ext), $this->allowed_extentions)) - { - while(file_exists($this->config->root_dir.$this->config->original_images_dir.$new_name)) - { - $new_base = pathinfo($new_name, PATHINFO_FILENAME); - if(preg_match('/_([0-9]+)$/', $new_base, $parts)) - $new_name = $base.'_'.($parts[1]+1).'.'.$ext; - else - $new_name = $base.'_1.'.$ext; - } - if(move_uploaded_file($filename, $this->config->root_dir.$this->config->original_images_dir.$new_name)) - return $new_name; - } - - return false; - } - - - /** - * Создание превью средствами gd - * @param $src_file исходный файл - * @param $dst_file файл с результатом - * @param max_w максимальная ширина - * @param max_h максимальная высота - * @return bool - */ - private function image_constrain_gd($src_file, $dst_file, $max_w, $max_h, $watermark=null, $watermark_offet_x=0, $watermark_offet_y=0, $watermark_opacity=1) - { - $quality = 100; - - // Параметры исходного изображения - @list($src_w, $src_h, $src_type) = array_values(getimagesize($src_file)); - $src_type = image_type_to_mime_type($src_type); - - if(empty($src_w) || empty($src_h) || empty($src_type)) - return false; - - // Нужно ли обрезать? - if (!$watermark && ($src_w <= $max_w) && ($src_h <= $max_h)) - { - // Нет - просто скопируем файл - if (!copy($src_file, $dst_file)) - return false; - return true; - } - - // Размеры превью при пропорциональном уменьшении - @list($dst_w, $dst_h) = $this->calc_contrain_size($src_w, $src_h, $max_w, $max_h); - - // Читаем изображение - switch ($src_type) - { - case 'image/jpeg': - $src_img = imageCreateFromJpeg($src_file); - break; - case 'image/gif': - $src_img = imageCreateFromGif($src_file); - break; - case 'image/png': - $src_img = imageCreateFromPng($src_file); - imagealphablending($src_img, true); - break; - default: - return false; - } - - if(empty($src_img)) - return false; - - $src_colors = imagecolorstotal($src_img); - - // create destination image (indexed, if possible) - if ($src_colors > 0 && $src_colors <= 256) - $dst_img = imagecreate($dst_w, $dst_h); - else - $dst_img = imagecreatetruecolor($dst_w, $dst_h); - - if (empty($dst_img)) - return false; - - $transparent_index = imagecolortransparent($src_img); - if ($transparent_index >= 0 && $transparent_index <= 128) - { - $t_c = imagecolorsforindex($src_img, $transparent_index); - $transparent_index = imagecolorallocate($dst_img, $t_c['red'], $t_c['green'], $t_c['blue']); - if ($transparent_index === false) - return false; - if (!imagefill($dst_img, 0, 0, $transparent_index)) - return false; - imagecolortransparent($dst_img, $transparent_index); - } - // or preserve alpha transparency for png - elseif ($src_type === 'image/png') - { - if (!imagealphablending($dst_img, false)) - return false; - $transparency = imagecolorallocatealpha($dst_img, 0, 0, 0, 127); - if (false === $transparency) - return false; - if (!imagefill($dst_img, 0, 0, $transparency)) - return false; - if (!imagesavealpha($dst_img, true)) - return false; - } - - // resample the image with new sizes - if (!imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h)) - return false; - - // Watermark - if(!empty($watermark) && is_readable($watermark)) - { - $overlay = imagecreatefrompng($watermark); - - // Get the size of overlay - $owidth = imagesx($overlay); - $oheight = imagesy($overlay); - - $watermark_x = min(($dst_w-$owidth)*$watermark_offet_x/100, $dst_w); - $watermark_y = min(($dst_h-$oheight)*$watermark_offet_y/100, $dst_h); - - imagecopy($dst_img, $overlay, $watermark_x, $watermark_y, 0, 0, $owidth, $oheight); - //imagecopymerge($dst_img, $overlay, $watermark_x, $watermark_y, 0, 0, $owidth, $oheight, $watermark_opacity*100); - - } - - - // recalculate quality value for png image - if ('image/png' === $src_type) - { - $quality = round(($quality / 100) * 10); - if ($quality < 1) - $quality = 1; - elseif ($quality > 10) - $quality = 10; - $quality = 10 - $quality; - } - - // Сохраняем изображение - switch ($src_type) - { - case 'image/jpeg': - return imageJpeg($dst_img, $dst_file, $quality); - case 'image/gif': - return imageGif($dst_img, $dst_file, $quality); - case 'image/png': - imagesavealpha($dst_img, true); - return imagePng($dst_img, $dst_file, $quality); - default: - return false; - } - } - - /** - * Создание превью средствами imagick - * @param $src_file исходный файл - * @param $dst_file файл с результатом - * @param max_w максимальная ширина - * @param max_h максимальная высота - * @return bool - */ - private function image_constrain_imagick($src_file, $dst_file, $max_w, $max_h, $watermark=null, $watermark_offet_x=0, $watermark_offet_y=0, $watermark_opacity=1, $sharpen=0.2) - { - $thumb = new Imagick(); - - // Читаем изображение - if(!$thumb->readImage($src_file)) - return false; - - // Размеры исходного изображения - $src_w = $thumb->getImageWidth(); - $src_h = $thumb->getImageHeight(); - - // Нужно ли обрезать? - if (!$watermark && ($src_w <= $max_w) && ($src_h <= $max_h)) - { - // Нет - просто скопируем файл - if (!copy($src_file, $dst_file)) - return false; - return true; - } - - // Размеры превью при пропорциональном уменьшении - list($dst_w, $dst_h) = $this->calc_contrain_size($src_w, $src_h, $max_w, $max_h); - - // Уменьшаем - $thumb->thumbnailImage($dst_w, $dst_h); - - // Устанавливаем водяной знак - if($watermark && is_readable($watermark)) - { - $overlay = new Imagick($watermark); - //$overlay->setImageOpacity($watermark_opacity); - //$overlay_compose = $overlay->getImageCompose(); - $overlay->evaluateImage(Imagick::EVALUATE_MULTIPLY, $watermark_opacity, Imagick::CHANNEL_ALPHA); - - // Get the size of overlay - $owidth = $overlay->getImageWidth(); - $oheight = $overlay->getImageHeight(); - - $watermark_x = min(($dst_w-$owidth)*$watermark_offet_x/100, $dst_w); - $watermark_y = min(($dst_h-$oheight)*$watermark_offet_y/100, $dst_h); - - } - - - // Анимированные gif требуют прохода по фреймам - foreach($thumb as $frame) - { - // Уменьшаем - $frame->thumbnailImage($dst_w, $dst_h); - - /* Set the virtual canvas to correct size */ - $frame->setImagePage($dst_w, $dst_h, 0, 0); - - // Наводим резкость - if($sharpen > 0) - $thumb->adaptiveSharpenImage($sharpen, $sharpen); - - if(isset($overlay) && is_object($overlay)) - { - // $frame->compositeImage($overlay, $overlay_compose, $watermark_x, $watermark_y, imagick::COLOR_ALPHA); - $frame->compositeImage($overlay, imagick::COMPOSITE_OVER, $watermark_x, $watermark_y, imagick::COLOR_ALPHA); - } - - } - - // Убираем комменты и т.п. из картинки - $thumb->stripImage(); - - // $thumb->setImageCompressionQuality(100); - - // Записываем картинку - if(!$thumb->writeImages($dst_file, true)) - return false; - - // Уборка - $thumb->destroy(); - if(isset($overlay) && is_object($overlay)) - $overlay->destroy(); - - return true; - } - - - /** - * Вычисляет размеры изображения, до которых нужно его пропорционально уменьшить, чтобы вписать в квадрат $max_w x $max_h - * @param src_w ширина исходного изображения - * @param src_h высота исходного изображения - * @param max_w максимальная ширина - * @param max_h максимальная высота - * @return array(w, h) - */ - private function calc_contrain_size($src_w, $src_h, $max_w = 0, $max_h = 0) - { - if($src_w == 0 || $src_h == 0) - return false; - - $dst_w = $src_w; - $dst_h = $src_h; - - if($src_w > $max_w && $max_w>0) - { - $dst_h = $src_h * ($max_w/$src_w); - $dst_w = $max_w; - } - if($dst_h > $max_h && $max_h>0) - { - $dst_w = $dst_w * ($max_h/$dst_h); - $dst_h = $max_h; - } - return array($dst_w, $dst_h); - } - - - private function files_identical($fn1, $fn2) - { - $buffer_len = 1024; - if(!$fp1 = fopen(dirname(dirname(__FILE__)).'/'.$fn1, 'rb')) - return FALSE; - - if(!$fp2 = fopen($fn2, 'rb')) { - fclose($fp1); - return FALSE; - } - - $same = TRUE; - while (!feof($fp1) and !feof($fp2)) - if(fread($fp1, $buffer_len) !== fread($fp2, $buffer_len)) { - $same = FALSE; - break; - } - - if(feof($fp1) !== feof($fp2)) - $same = FALSE; - - fclose($fp1); - fclose($fp2); - - return $same; - } - - private function correct_filename($filename) - { - $ru = explode('-', "А-а-Б-б-В-в-Ґ-ґ-Г-г-Д-д-Е-е-Ё-ё-Є-є-Ж-ж-З-з-И-и-І-і-Ї-ї-Й-й-К-к-Л-л-М-м-Н-н-О-о-П-п-Р-р-С-с-Т-т-У-у-Ф-ф-Х-х-Ц-ц-Ч-ч-Ш-ш-Щ-щ-Ъ-ъ-Ы-ы-Ь-ь-Э-э-Ю-ю-Я-я"); - $en = explode('-', "A-a-B-b-V-v-G-g-G-g-D-d-E-e-E-e-E-e-ZH-zh-Z-z-I-i-I-i-I-i-J-j-K-k-L-l-M-m-N-n-O-o-P-p-R-r-S-s-T-t-U-u-F-f-H-h-TS-ts-CH-ch-SH-sh-SCH-sch---Y-y---E-e-YU-yu-YA-ya"); - - $res = str_replace($ru, $en, $filename); - $res = preg_replace("/[\s]+/ui", '-', $res); - $res = preg_replace("/[^a-zA-Z0-9\.\-\_]+/ui", '', $res); - $res = strtolower($res); - return $res; - } - + private $allowed_extentions = array('png', 'gif', 'jpg', 'jpeg', 'ico'); + + public function __construct() + { + parent::__construct(); + } + + + /** + * Создание превью изображения + * @param $filename файл с изображением (без пути к файлу) + * @param max_w максимальная ширина + * @param max_h максимальная высота + * @return $string имя файла превью + */ + public function resize($filename) + { + list($source_file, $width, $height, $set_watermark) = $this->get_resize_params($filename); + + // Если вайл удаленный (http://), зальем его себе + if (substr($source_file, 0, 7) == 'http://') { + // Имя оригинального файла + if (!$original_file = $this->download_image($source_file)) { + return false; + } + + $resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark); + } else { + $original_file = $source_file; + } + + $resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark); + + + // Пути к папкам с картинками + $originals_dir = $this->config->root_dir.$this->config->original_images_dir; + $preview_dir = $this->config->root_dir.$this->config->resized_images_dir; + + $watermark_offet_x = $this->settings->watermark_offset_x; + $watermark_offet_y = $this->settings->watermark_offset_y; + + $sharpen = min(100, $this->settings->images_sharpen)/100; + $watermark_transparency = 1-min(100, $this->settings->watermark_transparency)/100; + + + if ($set_watermark && is_file($this->config->root_dir.$this->config->watermark_file)) { + $watermark = $this->config->root_dir.$this->config->watermark_file; + } else { + $watermark = null; + } + + if (class_exists('Imagick') && $this->config->use_imagick) { + $this->image_constrain_imagick($originals_dir.$original_file, $preview_dir.$resized_file, $width, $height, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_transparency, $sharpen); + } else { + $this->image_constrain_gd($originals_dir.$original_file, $preview_dir.$resized_file, $width, $height, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_transparency); + } + + return $preview_dir.$resized_file; + } + + public function add_resize_params($filename, $width=0, $height=0, $set_watermark=false) + { + if ('.' != ($dirname = pathinfo($filename, PATHINFO_DIRNAME))) { + $file = $dirname.'/'.pathinfo($filename, PATHINFO_FILENAME); + } else { + $file = pathinfo($filename, PATHINFO_FILENAME); + } + $ext = pathinfo($filename, PATHINFO_EXTENSION); + + if ($width>0 || $height>0) { + $resized_filename = $file.'.'.($width>0?$width:'').'x'.($height>0?$height:'').($set_watermark?'w':'').'.'.$ext; + } else { + $resized_filename = $file.'.'.($set_watermark?'w.':'').$ext; + } + + return $resized_filename; + } + + public function get_resize_params($filename) + { + // Определаяем параметры ресайза + if (!preg_match('/(.+)\.([0-9]*)x([0-9]*)(w)?\.([^\.]+)$/', $filename, $matches)) { + return false; + } + + $file = $matches[1]; // имя запрашиваемого файла + $width = $matches[2]; // ширина будущего изображения + $height = $matches[3]; // высота будущего изображения + $set_watermark = $matches[4] == 'w'; // ставить ли водяной знак + $ext = $matches[5]; // расширение файла + + return array($file.'.'.$ext, $width, $height, $set_watermark); + } + + + public function download_image($filename) + { + // Заливаем только есть такой файл есть в базе + $this->db->query('SELECT 1 FROM __images WHERE filename=? LIMIT 1', $filename); + if (!$this->db->result()) { + return false; + } + + // Имя оригинального файла + $basename = explode('&', pathinfo($filename, PATHINFO_BASENAME)); + $uploaded_file = array_shift($basename); + $base = urldecode(pathinfo($uploaded_file, PATHINFO_FILENAME)); + $ext = pathinfo($uploaded_file, PATHINFO_EXTENSION); + + // Если такой файл существует, нужно придумать другое название + $new_name = urldecode($uploaded_file); + + while (file_exists($this->config->root_dir.$this->config->original_images_dir.$new_name)) { + $new_base = pathinfo($new_name, PATHINFO_FILENAME); + if (preg_match('/_([0-9]+)$/', $new_base, $parts)) { + $new_name = $base.'_'.($parts[1]+1).'.'.$ext; + } else { + $new_name = $base.'_1.'.$ext; + } + } + $this->db->query('UPDATE __images SET filename=? WHERE filename=?', $new_name, $filename); + + // Перед долгим копированием займем это имя + fclose(fopen($this->config->root_dir.$this->config->original_images_dir.$new_name, 'w')); + copy($filename, $this->config->root_dir.$this->config->original_images_dir.$new_name); + return $new_name; + } + + public function upload_image($filename, $name) + { + // Имя оригинального файла + $name = $this->correct_filename($name); + $uploaded_file = $new_name = pathinfo($name, PATHINFO_BASENAME); + $base = pathinfo($uploaded_file, PATHINFO_FILENAME); + $ext = pathinfo($uploaded_file, PATHINFO_EXTENSION); + + if (in_array(strtolower($ext), $this->allowed_extentions)) { + while (file_exists($this->config->root_dir.$this->config->original_images_dir.$new_name)) { + $new_base = pathinfo($new_name, PATHINFO_FILENAME); + if (preg_match('/_([0-9]+)$/', $new_base, $parts)) { + $new_name = $base.'_'.($parts[1]+1).'.'.$ext; + } else { + $new_name = $base.'_1.'.$ext; + } + } + if (move_uploaded_file($filename, $this->config->root_dir.$this->config->original_images_dir.$new_name)) { + return $new_name; + } + } + + return false; + } + + + /** + * Создание превью средствами gd + * @param $src_file исходный файл + * @param $dst_file файл с результатом + * @param max_w максимальная ширина + * @param max_h максимальная высота + * @return bool + */ + private function image_constrain_gd($src_file, $dst_file, $max_w, $max_h, $watermark=null, $watermark_offet_x=0, $watermark_offet_y=0, $watermark_opacity=1) + { + $quality = 100; + + // Параметры исходного изображения + @list($src_w, $src_h, $src_type) = array_values(getimagesize($src_file)); + $src_type = image_type_to_mime_type($src_type); + + if (empty($src_w) || empty($src_h) || empty($src_type)) { + return false; + } + + // Нужно ли обрезать? + if (!$watermark && ($src_w <= $max_w) && ($src_h <= $max_h)) { + // Нет - просто скопируем файл + if (!copy($src_file, $dst_file)) { + return false; + } + return true; + } + + // Размеры превью при пропорциональном уменьшении + @list($dst_w, $dst_h) = $this->calc_contrain_size($src_w, $src_h, $max_w, $max_h); + + // Читаем изображение + switch ($src_type) { + case 'image/jpeg': + $src_img = imageCreateFromJpeg($src_file); + break; + case 'image/gif': + $src_img = imageCreateFromGif($src_file); + break; + case 'image/png': + $src_img = imageCreateFromPng($src_file); + imagealphablending($src_img, true); + break; + default: + return false; + } + + if (empty($src_img)) { + return false; + } + + $src_colors = imagecolorstotal($src_img); + + // create destination image (indexed, if possible) + if ($src_colors > 0 && $src_colors <= 256) { + $dst_img = imagecreate($dst_w, $dst_h); + } else { + $dst_img = imagecreatetruecolor($dst_w, $dst_h); + } + + if (empty($dst_img)) { + return false; + } + + $transparent_index = imagecolortransparent($src_img); + if ($transparent_index >= 0 && $transparent_index <= 128) { + $t_c = imagecolorsforindex($src_img, $transparent_index); + $transparent_index = imagecolorallocate($dst_img, $t_c['red'], $t_c['green'], $t_c['blue']); + if ($transparent_index === false) { + return false; + } + if (!imagefill($dst_img, 0, 0, $transparent_index)) { + return false; + } + imagecolortransparent($dst_img, $transparent_index); + } + // or preserve alpha transparency for png + elseif ($src_type === 'image/png') { + if (!imagealphablending($dst_img, false)) { + return false; + } + $transparency = imagecolorallocatealpha($dst_img, 0, 0, 0, 127); + if (false === $transparency) { + return false; + } + if (!imagefill($dst_img, 0, 0, $transparency)) { + return false; + } + if (!imagesavealpha($dst_img, true)) { + return false; + } + } + + // resample the image with new sizes + if (!imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h)) { + return false; + } + + // Watermark + if (!empty($watermark) && is_readable($watermark)) { + $overlay = imagecreatefrompng($watermark); + + // Get the size of overlay + $owidth = imagesx($overlay); + $oheight = imagesy($overlay); + + $watermark_x = min(($dst_w-$owidth)*$watermark_offet_x/100, $dst_w); + $watermark_y = min(($dst_h-$oheight)*$watermark_offet_y/100, $dst_h); + + imagecopy($dst_img, $overlay, $watermark_x, $watermark_y, 0, 0, $owidth, $oheight); + //imagecopymerge($dst_img, $overlay, $watermark_x, $watermark_y, 0, 0, $owidth, $oheight, $watermark_opacity*100); + } + + + // recalculate quality value for png image + if ('image/png' === $src_type) { + $quality = round(($quality / 100) * 10); + if ($quality < 1) { + $quality = 1; + } elseif ($quality > 10) { + $quality = 10; + } + $quality = 10 - $quality; + } + + // Сохраняем изображение + switch ($src_type) { + case 'image/jpeg': + return imageJpeg($dst_img, $dst_file, $quality); + case 'image/gif': + return imageGif($dst_img, $dst_file, $quality); + case 'image/png': + imagesavealpha($dst_img, true); + return imagePng($dst_img, $dst_file, $quality); + default: + return false; + } + } + + /** + * Создание превью средствами imagick + * @param $src_file исходный файл + * @param $dst_file файл с результатом + * @param max_w максимальная ширина + * @param max_h максимальная высота + * @return bool + */ + private function image_constrain_imagick($src_file, $dst_file, $max_w, $max_h, $watermark=null, $watermark_offet_x=0, $watermark_offet_y=0, $watermark_opacity=1, $sharpen=0.2) + { + $thumb = new Imagick(); + + // Читаем изображение + if (!$thumb->readImage($src_file)) { + return false; + } + + // Размеры исходного изображения + $src_w = $thumb->getImageWidth(); + $src_h = $thumb->getImageHeight(); + + // Нужно ли обрезать? + if (!$watermark && ($src_w <= $max_w) && ($src_h <= $max_h)) { + // Нет - просто скопируем файл + if (!copy($src_file, $dst_file)) { + return false; + } + return true; + } + + // Размеры превью при пропорциональном уменьшении + list($dst_w, $dst_h) = $this->calc_contrain_size($src_w, $src_h, $max_w, $max_h); + + // Уменьшаем + $thumb->thumbnailImage($dst_w, $dst_h); + + // Устанавливаем водяной знак + if ($watermark && is_readable($watermark)) { + $overlay = new Imagick($watermark); + //$overlay->setImageOpacity($watermark_opacity); + //$overlay_compose = $overlay->getImageCompose(); + $overlay->evaluateImage(Imagick::EVALUATE_MULTIPLY, $watermark_opacity, Imagick::CHANNEL_ALPHA); + + // Get the size of overlay + $owidth = $overlay->getImageWidth(); + $oheight = $overlay->getImageHeight(); + + $watermark_x = min(($dst_w-$owidth)*$watermark_offet_x/100, $dst_w); + $watermark_y = min(($dst_h-$oheight)*$watermark_offet_y/100, $dst_h); + } + + + // Анимированные gif требуют прохода по фреймам + foreach ($thumb as $frame) { + // Уменьшаем + $frame->thumbnailImage($dst_w, $dst_h); + + /* Set the virtual canvas to correct size */ + $frame->setImagePage($dst_w, $dst_h, 0, 0); + + // Наводим резкость + if ($sharpen > 0) { + $thumb->adaptiveSharpenImage($sharpen, $sharpen); + } + + if (isset($overlay) && is_object($overlay)) { + // $frame->compositeImage($overlay, $overlay_compose, $watermark_x, $watermark_y, imagick::COLOR_ALPHA); + $frame->compositeImage($overlay, imagick::COMPOSITE_OVER, $watermark_x, $watermark_y, imagick::COLOR_ALPHA); + } + } + + // Убираем комменты и т.п. из картинки + $thumb->stripImage(); + + // $thumb->setImageCompressionQuality(100); + + // Записываем картинку + if (!$thumb->writeImages($dst_file, true)) { + return false; + } + + // Уборка + $thumb->destroy(); + if (isset($overlay) && is_object($overlay)) { + $overlay->destroy(); + } + + return true; + } + + + /** + * Вычисляет размеры изображения, до которых нужно его пропорционально уменьшить, чтобы вписать в квадрат $max_w x $max_h + * @param src_w ширина исходного изображения + * @param src_h высота исходного изображения + * @param max_w максимальная ширина + * @param max_h максимальная высота + * @return array(w, h) + */ + private function calc_contrain_size($src_w, $src_h, $max_w = 0, $max_h = 0) + { + if ($src_w == 0 || $src_h == 0) { + return false; + } + + $dst_w = $src_w; + $dst_h = $src_h; + + if ($src_w > $max_w && $max_w>0) { + $dst_h = $src_h * ($max_w/$src_w); + $dst_w = $max_w; + } + if ($dst_h > $max_h && $max_h>0) { + $dst_w = $dst_w * ($max_h/$dst_h); + $dst_h = $max_h; + } + return array($dst_w, $dst_h); + } + + + private function files_identical($fn1, $fn2) + { + $buffer_len = 1024; + if (!$fp1 = fopen(dirname(dirname(__FILE__)).'/'.$fn1, 'rb')) { + return false; + } + + if (!$fp2 = fopen($fn2, 'rb')) { + fclose($fp1); + return false; + } + + $same = true; + while (!feof($fp1) and !feof($fp2)) { + if (fread($fp1, $buffer_len) !== fread($fp2, $buffer_len)) { + $same = false; + break; + } + } + + if (feof($fp1) !== feof($fp2)) { + $same = false; + } + + fclose($fp1); + fclose($fp2); + + return $same; + } + + private function correct_filename($filename) + { + $ru = explode('-', "А-а-Б-б-В-в-Ґ-ґ-Г-г-Д-д-Е-е-Ё-ё-Є-є-Ж-ж-З-з-И-и-І-і-Ї-ї-Й-й-К-к-Л-л-М-м-Н-н-О-о-П-п-Р-р-С-с-Т-т-У-у-Ф-ф-Х-х-Ц-ц-Ч-ч-Ш-ш-Щ-щ-Ъ-ъ-Ы-ы-Ь-ь-Э-э-Ю-ю-Я-я"); + $en = explode('-', "A-a-B-b-V-v-G-g-G-g-D-d-E-e-E-e-E-e-ZH-zh-Z-z-I-i-I-i-I-i-J-j-K-k-L-l-M-m-N-n-O-o-P-p-R-r-S-s-T-t-U-u-F-f-H-h-TS-ts-CH-ch-SH-sh-SCH-sch---Y-y---E-e-YU-yu-YA-ya"); + + $res = str_replace($ru, $en, $filename); + $res = preg_replace("/[\s]+/ui", '-', $res); + $res = preg_replace("/[^a-zA-Z0-9\.\-\_]+/ui", '', $res); + $res = strtolower($res); + return $res; + } } diff --git a/api/Managers.php b/api/Managers.php index d93273b..4523799 100755 --- a/api/Managers.php +++ b/api/Managers.php @@ -14,207 +14,204 @@ class Managers extends Simpla { - public $permissions_list = array('products', 'categories', 'brands', 'features', 'orders', 'labels', - 'users', 'groups', 'coupons', 'pages', 'blog', 'comments', 'feedbacks', 'import', 'export', - 'backup', 'stats', 'design', 'settings', 'currency', 'delivery', 'payment', 'managers', 'license'); - - public $passwd_file = "simpla/.passwd"; - - public function __construct() - { - // Для совсестимости с режимом CGI - if (isset($_SERVER['REDIRECT_REMOTE_USER']) && empty($_SERVER['PHP_AUTH_USER'])) - { - $_SERVER['PHP_AUTH_USER'] = $_SERVER['REDIRECT_REMOTE_USER']; - } - elseif(empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER["REMOTE_USER"])) - { - $_SERVER['PHP_AUTH_USER'] = $_SERVER["REMOTE_USER"]; - } - } - - public function get_managers() - { - $lines = explode("\n", @file_get_contents($this->config->root_dir.$this->passwd_file)); - $managers = array(); - foreach($lines as $line) - { - if(!empty($line)) - { - $manager = null; - $fields = explode(":", $line); - $manager = new stdClass(); - $manager->login = trim($fields[0]); - $manager->permissions = array(); - if(isset($fields[2])) - { - $manager->permissions = explode(",", $fields[2]); - foreach($manager->permissions as &$permission) - $permission = trim($permission); - } - else - $manager->permissions = $this->permissions_list; - - $managers[] = $manager; - } - } - return $managers; - } - - public function count_managers($filter = array()) - { - return count($this->get_managers()); - } - - public function get_manager($login = null) - { - // Если не запрашивается по логину, отдаём текущего менеджера или false - if(empty($login)) - if(!empty($_SERVER['PHP_AUTH_USER'])) - $login = $_SERVER['PHP_AUTH_USER']; - else - { - // Тестовый менеджер, если отключена авторизация - $m = new stdClass(); - $m->login = 'manager'; - $m->permissions = $this->permissions_list; - return $m; - } - - foreach($this->get_managers() as $manager) - { - if($manager->login == $login) - return $manager; - } - return false; - } - - public function add_manager($manager) - { - $manager = (object)$manager; - if(!empty($manager->login)) - $m[0] = $manager->login; - if(!empty($manager->password)) - { - // захешировать пароль - $m[1] = $this->crypt_apr1_md5($manager->password); - } - else - { - $m[1] = ""; - } - if(is_array($manager->permissions)) - { - if(count(array_diff($this->permissions_list, $manager->permissions))>0) - { - $m[2] = implode(",", $manager->permissions); - } - else - { - unset($m[2]); - } - } - $line = implode(":", $m); - file_put_contents($this->passwd_file, @file_get_contents($this->passwd_file)."\n".$line); - if($m = $this->get_manager($manager->login)) - return $m->login; - else - return false; - } - - public function update_manager($login, $manager) - { - $manager = (object)$manager; - // Не допускаем двоеточия в логине - if(!empty($manager->login)) - $manager->login = str_replace(":", "", $manager->login); - - $lines = explode("\n", @file_get_contents($this->passwd_file)); - $updated_flag = false; - foreach($lines as &$line) - { - $m = explode(":", $line); - if($m[0] == $login) - { - if(!empty($manager->login)) - $m[0] = $manager->login; - if(!empty($manager->password)) - { - // захешировать пароль - $m[1] = $this->crypt_apr1_md5($manager->password); - } - if(isset($manager->permissions) && is_array($manager->permissions)) - { - if(count(array_diff($this->permissions_list, $manager->permissions))>0) - { - $m[2] = implode(",", array_intersect($this->permissions_list, $manager->permissions)); - } - else - { - unset($m[2]); - } - } - $line = implode(":", $m); - $updated_flag = true; - } - } - if($updated_flag) - { - file_put_contents($this->passwd_file, implode("\n", $lines)); - if($m = $this->get_manager($manager->login)) - return $m->login; - } - return false; - } - - public function delete_manager($login) - { - $lines = explode("\n", @file_get_contents($this->passwd_file)); - foreach($lines as $i=>$line) - { - $m = explode(":", $line); - if($m[0] == $login) - unset($lines[$i]); - } - file_put_contents($this->passwd_file, implode("\n", $lines)); - return true; - } - - private function crypt_apr1_md5($plainpasswd) { - $salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8); - $len = strlen($plainpasswd); - $text = $plainpasswd.'$apr1$'.$salt; - $bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd)); - for($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); } - for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; } - $bin = pack("H32", md5($text)); - for($i = 0; $i < 1000; $i++) { - $new = ($i & 1) ? $plainpasswd : $bin; - if ($i % 3) $new .= $salt; - if ($i % 7) $new .= $plainpasswd; - $new .= ($i & 1) ? $bin : $plainpasswd; - $bin = pack("H32", md5($new)); - } - $tmp = ''; - for ($i = 0; $i < 5; $i++) { - $k = $i + 6; - $j = $i + 12; - if ($j == 16) $j = 5; - $tmp = $bin[$i].$bin[$k].$bin[$j].$tmp; - } - $tmp = chr(0).chr(0).$bin[11].$tmp; - $tmp = strtr(strrev(substr(base64_encode($tmp), 2)), - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); - return "$"."apr1"."$".$salt."$".$tmp; - } - - public function access($module) - { - $manager = $this->get_manager(); - if(is_array($manager->permissions)) - return in_array($module, $manager->permissions); - else - return false; - } + public $permissions_list = array('products', 'categories', 'brands', 'features', 'orders', 'labels', + 'users', 'groups', 'coupons', 'pages', 'blog', 'comments', 'feedbacks', 'import', 'export', + 'backup', 'stats', 'design', 'settings', 'currency', 'delivery', 'payment', 'managers', 'license'); + + public $passwd_file = "simpla/.passwd"; + + public function __construct() + { + // Для совсестимости с режимом CGI + if (isset($_SERVER['REDIRECT_REMOTE_USER']) && empty($_SERVER['PHP_AUTH_USER'])) { + $_SERVER['PHP_AUTH_USER'] = $_SERVER['REDIRECT_REMOTE_USER']; + } elseif (empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER["REMOTE_USER"])) { + $_SERVER['PHP_AUTH_USER'] = $_SERVER["REMOTE_USER"]; + } + } + + public function get_managers() + { + $lines = explode("\n", @file_get_contents($this->config->root_dir.$this->passwd_file)); + $managers = array(); + foreach ($lines as $line) { + if (!empty($line)) { + $manager = null; + $fields = explode(":", $line); + $manager = new stdClass(); + $manager->login = trim($fields[0]); + $manager->permissions = array(); + if (isset($fields[2])) { + $manager->permissions = explode(",", $fields[2]); + foreach ($manager->permissions as &$permission) { + $permission = trim($permission); + } + } else { + $manager->permissions = $this->permissions_list; + } + + $managers[] = $manager; + } + } + return $managers; + } + + public function count_managers($filter = array()) + { + return count($this->get_managers()); + } + + public function get_manager($login = null) + { + // Если не запрашивается по логину, отдаём текущего менеджера или false + if (empty($login)) { + if (!empty($_SERVER['PHP_AUTH_USER'])) { + $login = $_SERVER['PHP_AUTH_USER']; + } else { + // Тестовый менеджер, если отключена авторизация + $m = new stdClass(); + $m->login = 'manager'; + $m->permissions = $this->permissions_list; + return $m; + } + } + + foreach ($this->get_managers() as $manager) { + if ($manager->login == $login) { + return $manager; + } + } + return false; + } + + public function add_manager($manager) + { + $manager = (object)$manager; + if (!empty($manager->login)) { + $m[0] = $manager->login; + } + if (!empty($manager->password)) { + // захешировать пароль + $m[1] = $this->crypt_apr1_md5($manager->password); + } else { + $m[1] = ""; + } + if (is_array($manager->permissions)) { + if (count(array_diff($this->permissions_list, $manager->permissions))>0) { + $m[2] = implode(",", $manager->permissions); + } else { + unset($m[2]); + } + } + $line = implode(":", $m); + file_put_contents($this->passwd_file, @file_get_contents($this->passwd_file)."\n".$line); + if ($m = $this->get_manager($manager->login)) { + return $m->login; + } else { + return false; + } + } + + public function update_manager($login, $manager) + { + $manager = (object)$manager; + // Не допускаем двоеточия в логине + if (!empty($manager->login)) { + $manager->login = str_replace(":", "", $manager->login); + } + + $lines = explode("\n", @file_get_contents($this->passwd_file)); + $updated_flag = false; + foreach ($lines as &$line) { + $m = explode(":", $line); + if ($m[0] == $login) { + if (!empty($manager->login)) { + $m[0] = $manager->login; + } + if (!empty($manager->password)) { + // захешировать пароль + $m[1] = $this->crypt_apr1_md5($manager->password); + } + if (isset($manager->permissions) && is_array($manager->permissions)) { + if (count(array_diff($this->permissions_list, $manager->permissions))>0) { + $m[2] = implode(",", array_intersect($this->permissions_list, $manager->permissions)); + } else { + unset($m[2]); + } + } + $line = implode(":", $m); + $updated_flag = true; + } + } + if ($updated_flag) { + file_put_contents($this->passwd_file, implode("\n", $lines)); + if ($m = $this->get_manager($manager->login)) { + return $m->login; + } + } + return false; + } + + public function delete_manager($login) + { + $lines = explode("\n", @file_get_contents($this->passwd_file)); + foreach ($lines as $i=>$line) { + $m = explode(":", $line); + if ($m[0] == $login) { + unset($lines[$i]); + } + } + file_put_contents($this->passwd_file, implode("\n", $lines)); + return true; + } + + private function crypt_apr1_md5($plainpasswd) + { + $salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8); + $len = strlen($plainpasswd); + $text = $plainpasswd.'$apr1$'.$salt; + $bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd)); + for ($i = $len; $i > 0; $i -= 16) { + $text .= substr($bin, 0, min(16, $i)); + } + for ($i = $len; $i > 0; $i >>= 1) { + $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; + } + $bin = pack("H32", md5($text)); + for ($i = 0; $i < 1000; $i++) { + $new = ($i & 1) ? $plainpasswd : $bin; + if ($i % 3) { + $new .= $salt; + } + if ($i % 7) { + $new .= $plainpasswd; + } + $new .= ($i & 1) ? $bin : $plainpasswd; + $bin = pack("H32", md5($new)); + } + $tmp = ''; + for ($i = 0; $i < 5; $i++) { + $k = $i + 6; + $j = $i + 12; + if ($j == 16) { + $j = 5; + } + $tmp = $bin[$i].$bin[$k].$bin[$j].$tmp; + } + $tmp = chr(0).chr(0).$bin[11].$tmp; + $tmp = strtr(strrev(substr(base64_encode($tmp), 2)), + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + return "$"."apr1"."$".$salt."$".$tmp; + } + + public function access($module) + { + $manager = $this->get_manager(); + if (is_array($manager->permissions)) { + return in_array($module, $manager->permissions); + } else { + return false; + } + } } diff --git a/api/Money.php b/api/Money.php index 32e37fe..af4b146 100755 --- a/api/Money.php +++ b/api/Money.php @@ -13,144 +13,145 @@ class Money extends Simpla { - private $currencies = array(); - private $currency; + private $currencies = array(); + private $currency; - public function __construct() - { - parent::__construct(); + public function __construct() + { + parent::__construct(); - if(isset($this->settings->price_decimals_point)) - $this->decimals_point = $this->settings->price_decimals_point; + if (isset($this->settings->price_decimals_point)) { + $this->decimals_point = $this->settings->price_decimals_point; + } - if(isset($this->settings->price_thousands_separator)) - $this->thousands_separator = $this->settings->price_thousands_separator; + if (isset($this->settings->price_thousands_separator)) { + $this->thousands_separator = $this->settings->price_thousands_separator; + } - $this->design->smarty->registerPlugin('modifier', 'convert', array($this, 'convert')); + $this->design->smarty->registerPlugin('modifier', 'convert', array($this, 'convert')); - $this->init_currencies(); - } + $this->init_currencies(); + } - private function init_currencies() - { - $this->currencies = array(); - // Выбираем из базы валюты - $query = "SELECT id, name, sign, code, rate_from, rate_to, cents, position, enabled FROM __currencies ORDER BY position"; - $this->db->query($query); + private function init_currencies() + { + $this->currencies = array(); + // Выбираем из базы валюты + $query = "SELECT id, name, sign, code, rate_from, rate_to, cents, position, enabled FROM __currencies ORDER BY position"; + $this->db->query($query); - $results = $this->db->results(); + $results = $this->db->results(); - foreach($results as $c) - { - $this->currencies[$c->id] = $c; - } + foreach ($results as $c) { + $this->currencies[$c->id] = $c; + } - $this->currency = reset($this->currencies); + $this->currency = reset($this->currencies); + } - } + public function get_currencies($filter = array()) + { + $currencies = array(); + foreach ($this->currencies as $id=>$currency) { + if ((isset($filter['enabled']) && $filter['enabled'] == 1 && $currency->enabled) || empty($filter['enabled'])) { + $currencies[$id] = $currency; + } + } - public function get_currencies($filter = array()) - { - $currencies = array(); - foreach($this->currencies as $id=>$currency) - if((isset($filter['enabled']) && $filter['enabled'] == 1 && $currency->enabled) || empty($filter['enabled'])) - $currencies[$id] = $currency; + return $currencies; + } - return $currencies; - } + public function get_currency($id = null) + { + if (!empty($id) && is_integer($id) && isset($this->currencies[$id])) { + return $this->currencies[$id]; + } - public function get_currency($id = null) - { - if(!empty($id) && is_integer($id) && isset($this->currencies[$id])) - return $this->currencies[$id]; + if (!empty($id) && is_string($id)) { + foreach ($this->currencies as $currency) { + if ($currency->code == $id) { + return $currency; + } + } + } - if(!empty($id) && is_string($id)) - { - foreach($this->currencies as $currency) - { - if($currency->code == $id) - return $currency; - } - } + return $this->currency; + } - return $this->currency; - } - - public function add_currency($currency) - { - $query = $this->db->placehold('INSERT INTO __currencies + public function add_currency($currency) + { + $query = $this->db->placehold('INSERT INTO __currencies SET ?%', - $currency); + $currency); - if(!$this->db->query($query)) - return false; + if (!$this->db->query($query)) { + return false; + } - $id = $this->db->insert_id(); - $this->db->query("UPDATE __currencies SET position=id WHERE id=?", $id); - $this->init_currencies(); + $id = $this->db->insert_id(); + $this->db->query("UPDATE __currencies SET position=id WHERE id=?", $id); + $this->init_currencies(); - return $id; - } + return $id; + } - public function update_currency($id, $currency) - { - $query = $this->db->placehold('UPDATE __currencies + public function update_currency($id, $currency) + { + $query = $this->db->placehold('UPDATE __currencies SET ?% WHERE id in (?@)', - $currency, (array)$id); - if(!$this->db->query($query)) - return false; - - $this->init_currencies(); - return $id; - } - - public function delete_currency($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __currencies WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - } - $this->init_currencies(); - } - - - public function convert($price, $currency_id = null, $format = true) - { - if(isset($currency_id)) - { - if(is_numeric($currency_id)) - $currency = $this->get_currency((integer)$currency_id); - else - $currency = $this->get_currency((string)$currency_id); - } - elseif(isset($_SESSION['currency_id'])) - $currency = $this->get_currency($_SESSION['currency_id']); - else - $currency = current($this->get_currencies(array('enabled'=>1))); - - $result = $price; - - if(!empty($currency)) - { - // Умножим на курс валюты - $result = $result*$currency->rate_from/$currency->rate_to; - - // Точность отображения, знаков после запятой - $precision = isset($currency->cents)?$currency->cents:2; - } - - // Форматирование цены - if($format) - $result = number_format($result, $precision, $this->settings->decimals_point, $this->settings->thousands_separator); - else - $result = round($result, $precision); - - return $result; - } - - + $currency, (array)$id); + if (!$this->db->query($query)) { + return false; + } + + $this->init_currencies(); + return $id; + } + + public function delete_currency($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __currencies WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + } + $this->init_currencies(); + } + + + public function convert($price, $currency_id = null, $format = true) + { + if (isset($currency_id)) { + if (is_numeric($currency_id)) { + $currency = $this->get_currency((integer)$currency_id); + } else { + $currency = $this->get_currency((string)$currency_id); + } + } elseif (isset($_SESSION['currency_id'])) { + $currency = $this->get_currency($_SESSION['currency_id']); + } else { + $currency = current($this->get_currencies(array('enabled'=>1))); + } + + $result = $price; + + if (!empty($currency)) { + // Умножим на курс валюты + $result = $result*$currency->rate_from/$currency->rate_to; + + // Точность отображения, знаков после запятой + $precision = isset($currency->cents)?$currency->cents:2; + } + + // Форматирование цены + if ($format) { + $result = number_format($result, $precision, $this->settings->decimals_point, $this->settings->thousands_separator); + } else { + $result = round($result, $precision); + } + + return $result; + } } diff --git a/api/Notify.php b/api/Notify.php index aabaaa7..4f774b2 100755 --- a/api/Notify.php +++ b/api/Notify.php @@ -12,187 +12,192 @@ class Notify extends Simpla { - public function email($to, $subject, $message, $from = '', $reply_to = '') - { - $headers = "MIME-Version: 1.0\n" ; - $headers .= "Content-type: text/html; charset=utf-8; \r\n"; - $headers .= "From: $from\r\n"; - if(!empty($reply_to)) - $headers .= "reply-to: $reply_to\r\n"; - - $subject = "=?utf-8?B?".base64_encode($subject)."?="; - - @mail($to, $subject, $message, $headers); - } - - public function email_order_user($order_id) - { - if(!($order = $this->orders->get_order(intval($order_id))) || empty($order->email)) - return false; - - $purchases = $this->orders->get_purchases(array('order_id'=>$order->id)); - $this->design->assign('purchases', $purchases); - - $products_ids = array(); - $variants_ids = array(); - foreach($purchases as $purchase) - { - $products_ids[] = $purchase->product_id; - $variants_ids[] = $purchase->variant_id; - } - - $products = array(); - foreach($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) - $products[$p->id] = $p; - - $images = $this->products->get_images(array('product_id'=>$products_ids)); - foreach($images as $image) - $products[$image->product_id]->images[] = $image; - - $variants = array(); - foreach($this->variants->get_variants(array('id'=>$variants_ids)) as $v) - { - $variants[$v->id] = $v; - $products[$v->product_id]->variants[] = $v; - } - - foreach($purchases as &$purchase) - { - if(!empty($products[$purchase->product_id])) - $purchase->product = $products[$purchase->product_id]; - if(!empty($variants[$purchase->variant_id])) - $purchase->variant = $variants[$purchase->variant_id]; - } - - // Способ доставки - $delivery = $this->delivery->get_delivery($order->delivery_id); - $this->design->assign('delivery', $delivery); - - $this->design->assign('order', $order); - $this->design->assign('purchases', $purchases); - - // Отправляем письмо - // Если в шаблон не передавалась валюта, передадим - if ($this->design->smarty->getTemplateVars('currency') === null) - { - $this->design->assign('currency', current($this->money->get_currencies(array('enabled'=>1)))); - } - $email_template = $this->design->fetch($this->config->root_dir.'design/'.$this->settings->theme.'/html/email_order.tpl'); - $subject = $this->design->get_var('subject'); - $this->email($order->email, $subject, $email_template, $this->settings->notify_from_email); - - } - - - public function email_order_admin($order_id) - { - if(!($order = $this->orders->get_order(intval($order_id)))) - return false; - - $purchases = $this->orders->get_purchases(array('order_id'=>$order->id)); - $this->design->assign('purchases', $purchases); - - $products_ids = array(); - $variants_ids = array(); - foreach($purchases as $purchase) - { - $products_ids[] = $purchase->product_id; - $variants_ids[] = $purchase->variant_id; - } - - $products = array(); - foreach($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) - $products[$p->id] = $p; - - $images = $this->products->get_images(array('product_id'=>$products_ids)); - foreach($images as $image) - $products[$image->product_id]->images[] = $image; - - $variants = array(); - foreach($this->variants->get_variants(array('id'=>$variants_ids)) as $v) - { - $variants[$v->id] = $v; - $products[$v->product_id]->variants[] = $v; - } - - foreach($purchases as &$purchase) - { - if(!empty($products[$purchase->product_id])) - $purchase->product = $products[$purchase->product_id]; - if(!empty($variants[$purchase->variant_id])) - $purchase->variant = $variants[$purchase->variant_id]; - } - - // Способ доставки - $delivery = $this->delivery->get_delivery($order->delivery_id); - $this->design->assign('delivery', $delivery); - - // Пользователь - $user = $this->users->get_user(intval($order->user_id)); - $this->design->assign('user', $user); - - $this->design->assign('order', $order); - $this->design->assign('purchases', $purchases); - - // В основной валюте - $this->design->assign('main_currency', $this->money->get_currency()); - - // Отправляем письмо - $email_template = $this->design->fetch($this->config->root_dir.'simpla/design/html/email_order_admin.tpl'); - $subject = $this->design->get_var('subject'); - $this->email($this->settings->order_email, $subject, $email_template, $this->settings->notify_from_email); - - } - - - - public function email_comment_admin($comment_id) - { - if(!($comment = $this->comments->get_comment(intval($comment_id)))) - return false; - - if($comment->type == 'product') - $comment->product = $this->products->get_product(intval($comment->object_id)); - if($comment->type == 'blog') - $comment->post = $this->blog->get_post(intval($comment->object_id)); - - $this->design->assign('comment', $comment); - - // Отправляем письмо - $email_template = $this->design->fetch($this->config->root_dir.'simpla/design/html/email_comment_admin.tpl'); - $subject = $this->design->get_var('subject'); - $this->email($this->settings->comment_email, $subject, $email_template, $this->settings->notify_from_email); - } - - public function email_password_remind($user_id, $code) - { - if(!($user = $this->users->get_user(intval($user_id)))) - return false; - - $this->design->assign('user', $user); - $this->design->assign('code', $code); - - // Отправляем письмо - $email_template = $this->design->fetch($this->config->root_dir.'design/'.$this->settings->theme.'/html/email_password_remind.tpl'); - $subject = $this->design->get_var('subject'); - $this->email($user->email, $subject, $email_template, $this->settings->notify_from_email); - - $this->design->smarty->clearAssign('user'); - $this->design->smarty->clearAssign('code'); - } - - public function email_feedback_admin($feedback_id) - { - if(!($feedback = $this->feedbacks->get_feedback(intval($feedback_id)))) - return false; - - $this->design->assign('feedback', $feedback); - - // Отправляем письмо - $email_template = $this->design->fetch($this->config->root_dir.'simpla/design/html/email_feedback_admin.tpl'); - $subject = $this->design->get_var('subject'); - $this->email($this->settings->comment_email, $subject, $email_template, "$feedback->name <$feedback->email>", "$feedback->name <$feedback->email>"); - } - - + public function email($to, $subject, $message, $from = '', $reply_to = '') + { + $headers = "MIME-Version: 1.0\n" ; + $headers .= "Content-type: text/html; charset=utf-8; \r\n"; + $headers .= "From: $from\r\n"; + if (!empty($reply_to)) { + $headers .= "reply-to: $reply_to\r\n"; + } + + $subject = "=?utf-8?B?".base64_encode($subject)."?="; + + @mail($to, $subject, $message, $headers); + } + + public function email_order_user($order_id) + { + if (!($order = $this->orders->get_order(intval($order_id))) || empty($order->email)) { + return false; + } + + $purchases = $this->orders->get_purchases(array('order_id'=>$order->id)); + $this->design->assign('purchases', $purchases); + + $products_ids = array(); + $variants_ids = array(); + foreach ($purchases as $purchase) { + $products_ids[] = $purchase->product_id; + $variants_ids[] = $purchase->variant_id; + } + + $products = array(); + foreach ($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) { + $products[$p->id] = $p; + } + + $images = $this->products->get_images(array('product_id'=>$products_ids)); + foreach ($images as $image) { + $products[$image->product_id]->images[] = $image; + } + + $variants = array(); + foreach ($this->variants->get_variants(array('id'=>$variants_ids)) as $v) { + $variants[$v->id] = $v; + $products[$v->product_id]->variants[] = $v; + } + + foreach ($purchases as &$purchase) { + if (!empty($products[$purchase->product_id])) { + $purchase->product = $products[$purchase->product_id]; + } + if (!empty($variants[$purchase->variant_id])) { + $purchase->variant = $variants[$purchase->variant_id]; + } + } + + // Способ доставки + $delivery = $this->delivery->get_delivery($order->delivery_id); + $this->design->assign('delivery', $delivery); + + $this->design->assign('order', $order); + $this->design->assign('purchases', $purchases); + + // Отправляем письмо + // Если в шаблон не передавалась валюта, передадим + if ($this->design->smarty->getTemplateVars('currency') === null) { + $this->design->assign('currency', current($this->money->get_currencies(array('enabled'=>1)))); + } + $email_template = $this->design->fetch($this->config->root_dir.'design/'.$this->settings->theme.'/html/email_order.tpl'); + $subject = $this->design->get_var('subject'); + $this->email($order->email, $subject, $email_template, $this->settings->notify_from_email); + } + + + public function email_order_admin($order_id) + { + if (!($order = $this->orders->get_order(intval($order_id)))) { + return false; + } + + $purchases = $this->orders->get_purchases(array('order_id'=>$order->id)); + $this->design->assign('purchases', $purchases); + + $products_ids = array(); + $variants_ids = array(); + foreach ($purchases as $purchase) { + $products_ids[] = $purchase->product_id; + $variants_ids[] = $purchase->variant_id; + } + + $products = array(); + foreach ($this->products->get_products(array('id'=>$products_ids, 'limit' => count($products_ids))) as $p) { + $products[$p->id] = $p; + } + + $images = $this->products->get_images(array('product_id'=>$products_ids)); + foreach ($images as $image) { + $products[$image->product_id]->images[] = $image; + } + + $variants = array(); + foreach ($this->variants->get_variants(array('id'=>$variants_ids)) as $v) { + $variants[$v->id] = $v; + $products[$v->product_id]->variants[] = $v; + } + + foreach ($purchases as &$purchase) { + if (!empty($products[$purchase->product_id])) { + $purchase->product = $products[$purchase->product_id]; + } + if (!empty($variants[$purchase->variant_id])) { + $purchase->variant = $variants[$purchase->variant_id]; + } + } + + // Способ доставки + $delivery = $this->delivery->get_delivery($order->delivery_id); + $this->design->assign('delivery', $delivery); + + // Пользователь + $user = $this->users->get_user(intval($order->user_id)); + $this->design->assign('user', $user); + + $this->design->assign('order', $order); + $this->design->assign('purchases', $purchases); + + // В основной валюте + $this->design->assign('main_currency', $this->money->get_currency()); + + // Отправляем письмо + $email_template = $this->design->fetch($this->config->root_dir.'simpla/design/html/email_order_admin.tpl'); + $subject = $this->design->get_var('subject'); + $this->email($this->settings->order_email, $subject, $email_template, $this->settings->notify_from_email); + } + + + + public function email_comment_admin($comment_id) + { + if (!($comment = $this->comments->get_comment(intval($comment_id)))) { + return false; + } + + if ($comment->type == 'product') { + $comment->product = $this->products->get_product(intval($comment->object_id)); + } + if ($comment->type == 'blog') { + $comment->post = $this->blog->get_post(intval($comment->object_id)); + } + + $this->design->assign('comment', $comment); + + // Отправляем письмо + $email_template = $this->design->fetch($this->config->root_dir.'simpla/design/html/email_comment_admin.tpl'); + $subject = $this->design->get_var('subject'); + $this->email($this->settings->comment_email, $subject, $email_template, $this->settings->notify_from_email); + } + + public function email_password_remind($user_id, $code) + { + if (!($user = $this->users->get_user(intval($user_id)))) { + return false; + } + + $this->design->assign('user', $user); + $this->design->assign('code', $code); + + // Отправляем письмо + $email_template = $this->design->fetch($this->config->root_dir.'design/'.$this->settings->theme.'/html/email_password_remind.tpl'); + $subject = $this->design->get_var('subject'); + $this->email($user->email, $subject, $email_template, $this->settings->notify_from_email); + + $this->design->smarty->clearAssign('user'); + $this->design->smarty->clearAssign('code'); + } + + public function email_feedback_admin($feedback_id) + { + if (!($feedback = $this->feedbacks->get_feedback(intval($feedback_id)))) { + return false; + } + + $this->design->assign('feedback', $feedback); + + // Отправляем письмо + $email_template = $this->design->fetch($this->config->root_dir.'simpla/design/html/email_feedback_admin.tpl'); + $subject = $this->design->get_var('subject'); + $this->email($this->settings->comment_email, $subject, $email_template, "$feedback->name <$feedback->email>", "$feedback->name <$feedback->email>"); + } } diff --git a/api/Orders.php b/api/Orders.php index cbc3826..4cc0e17 100755 --- a/api/Orders.php +++ b/api/Orders.php @@ -15,70 +15,79 @@ class Orders extends Simpla { - public function get_order($id) - { - if(is_int($id)) - $where = $this->db->placehold(' WHERE o.id=? ', intval($id)); - else - $where = $this->db->placehold(' WHERE o.url=? ', $id); - - $query = $this->db->placehold("SELECT o.id, o.delivery_id, o.delivery_price, o.separate_delivery, + public function get_order($id) + { + if (is_int($id)) { + $where = $this->db->placehold(' WHERE o.id=? ', intval($id)); + } else { + $where = $this->db->placehold(' WHERE o.url=? ', $id); + } + + $query = $this->db->placehold("SELECT o.id, o.delivery_id, o.delivery_price, o.separate_delivery, o.payment_method_id, o.paid, o.payment_date, o.closed, o.discount, o.coupon_code, o.coupon_discount, o.date, o.user_id, o.name, o.address, o.phone, o.email, o.comment, o.status, o.url, o.total_price, o.note, o.ip FROM __orders o $where LIMIT 1"); - if($this->db->query($query)) - return $this->db->result(); - else - return false; - } - - public function get_orders($filter = array()) - { - // По умолчанию - $limit = 100; - $page = 1; - $keyword_filter = ''; - $label_filter = ''; - $status_filter = ''; - $user_filter = ''; - $modified_since_filter = ''; - $id_filter = ''; - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - - - if(isset($filter['status'])) - $status_filter = $this->db->placehold('AND o.status = ?', intval($filter['status'])); - - if(isset($filter['id'])) - $id_filter = $this->db->placehold('AND o.id in(?@)', (array)$filter['id']); - - if(isset($filter['user_id'])) - $user_filter = $this->db->placehold('AND o.user_id = ?', intval($filter['user_id'])); - - if(isset($filter['modified_since'])) - $modified_since_filter = $this->db->placehold('AND o.modified > ?', $filter['modified_since']); - - if(!empty($filter['label'])) - $label_filter = $this->db->placehold('AND ol.label_id = ?', $filter['label']); - - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (o.id = "'.$this->db->escape(trim($keyword)).'" OR o.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR REPLACE(o.phone, "-", "") LIKE "%'.$this->db->escape(str_replace('-', '', trim($keyword))).'%" OR o.address LIKE "%'.$this->db->escape(trim($keyword)).'%" )'); - } - - // Выбираем заказы - $query = $this->db->placehold("SELECT o.id, o.delivery_id, o.delivery_price, o.separate_delivery, + if ($this->db->query($query)) { + return $this->db->result(); + } else { + return false; + } + } + + public function get_orders($filter = array()) + { + // По умолчанию + $limit = 100; + $page = 1; + $keyword_filter = ''; + $label_filter = ''; + $status_filter = ''; + $user_filter = ''; + $modified_since_filter = ''; + $id_filter = ''; + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + + + if (isset($filter['status'])) { + $status_filter = $this->db->placehold('AND o.status = ?', intval($filter['status'])); + } + + if (isset($filter['id'])) { + $id_filter = $this->db->placehold('AND o.id in(?@)', (array)$filter['id']); + } + + if (isset($filter['user_id'])) { + $user_filter = $this->db->placehold('AND o.user_id = ?', intval($filter['user_id'])); + } + + if (isset($filter['modified_since'])) { + $modified_since_filter = $this->db->placehold('AND o.modified > ?', $filter['modified_since']); + } + + if (!empty($filter['label'])) { + $label_filter = $this->db->placehold('AND ol.label_id = ?', $filter['label']); + } + + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (o.id = "'.$this->db->escape(trim($keyword)).'" OR o.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR REPLACE(o.phone, "-", "") LIKE "%'.$this->db->escape(str_replace('-', '', trim($keyword))).'%" OR o.address LIKE "%'.$this->db->escape(trim($keyword)).'%" )'); + } + } + + // Выбираем заказы + $query = $this->db->placehold("SELECT o.id, o.delivery_id, o.delivery_price, o.separate_delivery, o.payment_method_id, o.paid, o.payment_date, o.closed, o.discount, o.coupon_code, o.coupon_discount, o.date, o.user_id, o.name, o.address, o.phone, o.email, o.comment, o.status, o.url, o.total_price, o.note @@ -86,158 +95,160 @@ public function get_orders($filter = array()) LEFT JOIN __orders_labels AS ol ON o.id=ol.order_id WHERE 1 $id_filter $status_filter $user_filter $keyword_filter $label_filter $modified_since_filter GROUP BY o.id ORDER BY status, id DESC $sql_limit", "%Y-%m-%d"); - $this->db->query($query); - $orders = array(); - foreach($this->db->results() as $order) - $orders[$order->id] = $order; - return $orders; - } - - public function count_orders($filter = array()) - { - $keyword_filter = ''; - $label_filter = ''; - $status_filter = ''; - $user_filter = ''; - - if(isset($filter['status'])) - $status_filter = $this->db->placehold('AND o.status = ?', intval($filter['status'])); - - if(isset($filter['user_id'])) - $user_filter = $this->db->placehold('AND o.user_id = ?', intval($filter['user_id'])); - - if(!empty($filter['label'])) - $label_filter = $this->db->placehold('AND ol.label_id = ?', $filter['label']); - - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (o.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR REPLACE(o.phone, "-", "") LIKE "%'.$this->db->escape(str_replace('-', '', trim($keyword))).'%" OR o.address LIKE "%'.$this->db->escape(trim($keyword)).'%" )'); - } - - // Выбираем заказы - $query = $this->db->placehold("SELECT COUNT(DISTINCT id) as count + $this->db->query($query); + $orders = array(); + foreach ($this->db->results() as $order) { + $orders[$order->id] = $order; + } + return $orders; + } + + public function count_orders($filter = array()) + { + $keyword_filter = ''; + $label_filter = ''; + $status_filter = ''; + $user_filter = ''; + + if (isset($filter['status'])) { + $status_filter = $this->db->placehold('AND o.status = ?', intval($filter['status'])); + } + + if (isset($filter['user_id'])) { + $user_filter = $this->db->placehold('AND o.user_id = ?', intval($filter['user_id'])); + } + + if (!empty($filter['label'])) { + $label_filter = $this->db->placehold('AND ol.label_id = ?', $filter['label']); + } + + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (o.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR REPLACE(o.phone, "-", "") LIKE "%'.$this->db->escape(str_replace('-', '', trim($keyword))).'%" OR o.address LIKE "%'.$this->db->escape(trim($keyword)).'%" )'); + } + } + + // Выбираем заказы + $query = $this->db->placehold("SELECT COUNT(DISTINCT id) as count FROM __orders AS o LEFT JOIN __orders_labels AS ol ON o.id=ol.order_id WHERE 1 $status_filter $user_filter $label_filter $keyword_filter"); - $this->db->query($query); - return $this->db->result('count'); - } - - public function update_order($id, $order) - { - $query = $this->db->placehold("UPDATE __orders SET ?%, modified=now() WHERE id=? LIMIT 1", $order, intval($id)); - $this->db->query($query); - $this->update_total_price(intval($id)); - return $id; - } - - public function delete_order($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __purchases WHERE order_id=?", $id); - $this->db->query($query); - - $query = $this->db->placehold("DELETE FROM __orders_labels WHERE order_id=?", $id); - $this->db->query($query); - - $query = $this->db->placehold("DELETE FROM __orders WHERE id=? LIMIT 1", $id); - $this->db->query($query); - } - } - - public function add_order($order) - { - $order = (object)$order; - $order->url = md5(uniqid($this->config->salt, true)); - $set_curr_date = ''; - if(empty($order->date)) - $set_curr_date = ', date=now()'; - $query = $this->db->placehold("INSERT INTO __orders SET ?%$set_curr_date", $order); - $this->db->query($query); - $id = $this->db->insert_id(); - return $id; - } - - public function get_label($id) - { - $query = $this->db->placehold("SELECT * FROM __labels WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - return $this->db->result(); - } - - public function get_labels() - { - $query = $this->db->placehold("SELECT * FROM __labels ORDER BY position"); - $this->db->query($query); - return $this->db->results(); - } - - /* - * - * Создание метки заказов - * @param $label - * - */ - public function add_label($label) - { - $query = $this->db->placehold('INSERT INTO __labels SET ?%', $label); - if(!$this->db->query($query)) - return false; - - $id = $this->db->insert_id(); - $this->db->query("UPDATE __labels SET position=id WHERE id=?", $id); - return $id; - } - - - /* - * - * Обновить метку - * @param $id, $label - * - */ - public function update_label($id, $label) - { - $query = $this->db->placehold("UPDATE __labels SET ?% WHERE id in(?@) LIMIT ?", $label, (array)$id, count((array)$id)); - $this->db->query($query); - return $id; - } - - /* - * - * Удалить метку - * @param $id - * - */ - public function delete_label($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __orders_labels WHERE label_id=?", intval($id)); - if($this->db->query($query)) - { - $query = $this->db->placehold("DELETE FROM __labels WHERE id=? LIMIT 1", intval($id)); - return $this->db->query($query); - } - else - { - return false; - } - } - } - - public function get_order_labels($order_id = array()) - { - if(empty($order_id)) - return array(); - - $label_id_filter = $this->db->placehold('AND order_id in(?@)', (array)$order_id); - - $query = $this->db->placehold("SELECT ol.order_id, l.id, l.name, l.color, l.position + $this->db->query($query); + return $this->db->result('count'); + } + + public function update_order($id, $order) + { + $query = $this->db->placehold("UPDATE __orders SET ?%, modified=now() WHERE id=? LIMIT 1", $order, intval($id)); + $this->db->query($query); + $this->update_total_price(intval($id)); + return $id; + } + + public function delete_order($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __purchases WHERE order_id=?", $id); + $this->db->query($query); + + $query = $this->db->placehold("DELETE FROM __orders_labels WHERE order_id=?", $id); + $this->db->query($query); + + $query = $this->db->placehold("DELETE FROM __orders WHERE id=? LIMIT 1", $id); + $this->db->query($query); + } + } + + public function add_order($order) + { + $order = (object)$order; + $order->url = md5(uniqid($this->config->salt, true)); + $set_curr_date = ''; + if (empty($order->date)) { + $set_curr_date = ', date=now()'; + } + $query = $this->db->placehold("INSERT INTO __orders SET ?%$set_curr_date", $order); + $this->db->query($query); + $id = $this->db->insert_id(); + return $id; + } + + public function get_label($id) + { + $query = $this->db->placehold("SELECT * FROM __labels WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + return $this->db->result(); + } + + public function get_labels() + { + $query = $this->db->placehold("SELECT * FROM __labels ORDER BY position"); + $this->db->query($query); + return $this->db->results(); + } + + /* + * + * Создание метки заказов + * @param $label + * + */ + public function add_label($label) + { + $query = $this->db->placehold('INSERT INTO __labels SET ?%', $label); + if (!$this->db->query($query)) { + return false; + } + + $id = $this->db->insert_id(); + $this->db->query("UPDATE __labels SET position=id WHERE id=?", $id); + return $id; + } + + + /* + * + * Обновить метку + * @param $id, $label + * + */ + public function update_label($id, $label) + { + $query = $this->db->placehold("UPDATE __labels SET ?% WHERE id in(?@) LIMIT ?", $label, (array)$id, count((array)$id)); + $this->db->query($query); + return $id; + } + + /* + * + * Удалить метку + * @param $id + * + */ + public function delete_label($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __orders_labels WHERE label_id=?", intval($id)); + if ($this->db->query($query)) { + $query = $this->db->placehold("DELETE FROM __labels WHERE id=? LIMIT 1", intval($id)); + return $this->db->query($query); + } else { + return false; + } + } + } + + public function get_order_labels($order_id = array()) + { + if (empty($order_id)) { + return array(); + } + + $label_id_filter = $this->db->placehold('AND order_id in(?@)', (array)$order_id); + + $query = $this->db->placehold("SELECT ol.order_id, l.id, l.name, l.color, l.position FROM __labels l LEFT JOIN __orders_labels ol ON ol.label_id = l.id WHERE 1 @@ -245,295 +256,307 @@ public function get_order_labels($order_id = array()) ORDER BY position "); - $this->db->query($query); - return $this->db->results(); - } - - public function update_order_labels($id, $labels_ids) - { - $labels_ids = (array)$labels_ids; - $query = $this->db->placehold("DELETE FROM __orders_labels WHERE order_id=?", intval($id)); - $this->db->query($query); - if(is_array($labels_ids)) - foreach($labels_ids as $l_id) - $this->db->query("INSERT INTO __orders_labels SET order_id=?, label_id=?", $id, $l_id); - } - - public function add_order_labels($id, $labels_ids) - { - $labels_ids = (array)$labels_ids; - if(is_array($labels_ids)) - foreach($labels_ids as $l_id) - { - $this->db->query("INSERT IGNORE INTO __orders_labels SET order_id=?, label_id=?", $id, $l_id); - } - } - - public function delete_order_labels($id, $labels_ids) - { - $labels_ids = (array)$labels_ids; - if(is_array($labels_ids)) - foreach($labels_ids as $l_id) - $this->db->query("DELETE FROM __orders_labels WHERE order_id=? AND label_id=?", $id, $l_id); - } - - - public function get_purchase($id) - { - $query = $this->db->placehold("SELECT * FROM __purchases WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - return $this->db->result(); - } - - public function get_purchases($filter = array()) - { - $order_id_filter = ''; - if(!empty($filter['order_id'])) - $order_id_filter = $this->db->placehold('AND order_id in(?@)', (array)$filter['order_id']); - - $query = $this->db->placehold("SELECT * FROM __purchases WHERE 1 $order_id_filter ORDER BY id"); - $this->db->query($query); - return $this->db->results(); - } - - public function update_purchase($id, $purchase) - { - $purchase = (object)$purchase; - $old_purchase = $this->get_purchase($id); - if(!$old_purchase) - return false; - - $order = $this->get_order(intval($old_purchase->order_id)); - if(!$order) - return false; - - // Не допустить нехватки на складе - $variant = $this->variants->get_variant($purchase->variant_id); - if($order->closed && !empty($purchase->amount) && !empty($variant) && !$variant->infinity && $variant->stock<($purchase->amount-$old_purchase->amount)) - return false; - - // Если заказ закрыт, нужно обновить склад при изменении покупки - if($order->closed && !empty($purchase->amount)) - { - if($old_purchase->variant_id != $purchase->variant_id) - { - if(!empty($old_purchase->variant_id)) - { - $query = $this->db->placehold("UPDATE __variants SET stock=stock+? WHERE id=? AND stock IS NOT NULL LIMIT 1", $old_purchase->amount, $old_purchase->variant_id); - $this->db->query($query); - } - if(!empty($purchase->variant_id)) - { - $query = $this->db->placehold("UPDATE __variants SET stock=stock-? WHERE id=? AND stock IS NOT NULL LIMIT 1", $purchase->amount, $purchase->variant_id); - $this->db->query($query); - } - } - elseif(!empty($purchase->variant_id)) - { - $query = $this->db->placehold("UPDATE __variants SET stock=stock+(?) WHERE id=? AND stock IS NOT NULL LIMIT 1", $old_purchase->amount - $purchase->amount, $purchase->variant_id); - $this->db->query($query); - } - } - - $query = $this->db->placehold("UPDATE __purchases SET ?% WHERE id=? LIMIT 1", $purchase, intval($id)); - $this->db->query($query); - $this->update_total_price($order->id); - return $id; - } - - public function add_purchase($purchase) - { - $purchase = (object)$purchase; - if(!empty($purchase->variant_id)) - { - $variant = $this->variants->get_variant($purchase->variant_id); - if(empty($variant)) - return false; - $product = $this->products->get_product(intval($variant->product_id)); - if(empty($product)) - return false; - } - - $order = $this->get_order(intval($purchase->order_id)); - if(empty($order)) - return false; - - // Не допустить нехватки на складе - if($order->closed && !empty($purchase->amount) && !$variant->infinity && $variant->stock<$purchase->amount) - return false; - - if(!isset($purchase->product_id) && isset($variant)) - $purchase->product_id = $variant->product_id; - - if(!isset($purchase->product_name) && !empty($product)) - $purchase->product_name = $product->name; - - if(!isset($purchase->sku) && !empty($variant)) - $purchase->sku = $variant->sku; - - if(!isset($purchase->variant_name) && !empty($variant)) - $purchase->variant_name = $variant->name; - - if(!isset($purchase->price) && !empty($variant)) - $purchase->price = $variant->price; - - if(!isset($purchase->amount)) - $purchase->amount = 1; - - // Если заказ закрыт, нужно обновить склад при добавлении покупки - if($order->closed && !empty($purchase->amount) && !empty($variant->id)) - { - $stock_diff = $purchase->amount; - $query = $this->db->placehold("UPDATE __variants SET stock=stock-? WHERE id=? AND stock IS NOT NULL LIMIT 1", $stock_diff, $variant->id); - $this->db->query($query); - } - - $query = $this->db->placehold("INSERT INTO __purchases SET ?%", $purchase); - $this->db->query($query); - $purchase_id = $this->db->insert_id(); - - $this->update_total_price($order->id); - return $purchase_id; - } - - public function delete_purchase($id) - { - $purchase = $this->get_purchase($id); - if(!$purchase) - return false; - - $order = $this->get_order(intval($purchase->order_id)); - if(!$order) - return false; - - // Если заказ закрыт, нужно обновить склад при изменении покупки - if($order->closed && !empty($purchase->amount)) - { - $stock_diff = $purchase->amount; - $query = $this->db->placehold("UPDATE __variants SET stock=stock+? WHERE id=? AND stock IS NOT NULL LIMIT 1", $stock_diff, $purchase->variant_id); - $this->db->query($query); - } - - $query = $this->db->placehold("DELETE FROM __purchases WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - $this->update_total_price($order->id); - return true; - } - - - public function close($order_id) - { - $order = $this->get_order(intval($order_id)); - if(empty($order)) - return false; - - if(!$order->closed) - { - $variants_amounts = array(); - $purchases = $this->get_purchases(array('order_id'=>$order->id)); - foreach($purchases as $purchase) - { - if(isset($variants_amounts[$purchase->variant_id])) - $variants_amounts[$purchase->variant_id] += $purchase->amount; - else - $variants_amounts[$purchase->variant_id] = $purchase->amount; - } - - foreach($variants_amounts as $id=>$amount) - { - $variant = $this->variants->get_variant($id); - if(empty($variant) || ($variant->stock<$amount)) - return false; - } - foreach($purchases as $purchase) - { - $variant = $this->variants->get_variant($purchase->variant_id); - if(!$variant->infinity) - { - $new_stock = $variant->stock-$purchase->amount; - $this->variants->update_variant($variant->id, array('stock'=>$new_stock)); - } - } - $query = $this->db->placehold("UPDATE __orders SET closed=1, modified=NOW() WHERE id=? LIMIT 1", $order->id); - $this->db->query($query); - } - return $order->id; - } - - public function open($order_id) - { - $order = $this->get_order(intval($order_id)); - if(empty($order)) - return false; - - if($order->closed) - { - $purchases = $this->get_purchases(array('order_id'=>$order->id)); - foreach($purchases as $purchase) - { - $variant = $this->variants->get_variant($purchase->variant_id); - if($variant && !$variant->infinity) - { - $new_stock = $variant->stock+$purchase->amount; - $this->variants->update_variant($variant->id, array('stock'=>$new_stock)); - } - } - $query = $this->db->placehold("UPDATE __orders SET closed=0, modified=NOW() WHERE id=? LIMIT 1", $order->id); - $this->db->query($query); - } - return $order->id; - } - - public function pay($order_id) - { - $order = $this->get_order(intval($order_id)); - if(empty($order)) - return false; - - if(!$this->close($order->id)) - { - return false; - } - $query = $this->db->placehold("UPDATE __orders SET payment_status=1, payment_date=NOW(), modified=NOW() WHERE id=? LIMIT 1", $order->id); - $this->db->query($query); - return $order->id; - } - - private function update_total_price($order_id) - { - $order = $this->get_order(intval($order_id)); - if(empty($order)) - return false; - - $query = $this->db->placehold("UPDATE __orders o SET o.total_price=IFNULL((SELECT SUM(p.price*p.amount)*(100-o.discount)/100 FROM __purchases p WHERE p.order_id=o.id), 0)+o.delivery_price*(1-o.separate_delivery)-o.coupon_discount, modified=NOW() WHERE o.id=? LIMIT 1", $order->id); - $this->db->query($query); - return $order->id; - } - - - public function get_next_order($id, $status = null) - { - $f = ''; - if($status!==null) - $f = $this->db->placehold('AND status=?', $status); - $this->db->query("SELECT MIN(id) as id FROM __orders WHERE id>? $f LIMIT 1", $id); - $next_id = $this->db->result('id'); - if($next_id) - return $this->get_order(intval($next_id)); - else - return false; - } - - public function get_prev_order($id, $status = null) - { - $f = ''; - if($status !== null) - $f = $this->db->placehold('AND status=?', $status); - $this->db->query("SELECT MAX(id) as id FROM __orders WHERE iddb->result('id'); - if($prev_id) - return $this->get_order(intval($prev_id)); - else - return false; - } + $this->db->query($query); + return $this->db->results(); + } + + public function update_order_labels($id, $labels_ids) + { + $labels_ids = (array)$labels_ids; + $query = $this->db->placehold("DELETE FROM __orders_labels WHERE order_id=?", intval($id)); + $this->db->query($query); + if (is_array($labels_ids)) { + foreach ($labels_ids as $l_id) { + $this->db->query("INSERT INTO __orders_labels SET order_id=?, label_id=?", $id, $l_id); + } + } + } + + public function add_order_labels($id, $labels_ids) + { + $labels_ids = (array)$labels_ids; + if (is_array($labels_ids)) { + foreach ($labels_ids as $l_id) { + $this->db->query("INSERT IGNORE INTO __orders_labels SET order_id=?, label_id=?", $id, $l_id); + } + } + } + + public function delete_order_labels($id, $labels_ids) + { + $labels_ids = (array)$labels_ids; + if (is_array($labels_ids)) { + foreach ($labels_ids as $l_id) { + $this->db->query("DELETE FROM __orders_labels WHERE order_id=? AND label_id=?", $id, $l_id); + } + } + } + + + public function get_purchase($id) + { + $query = $this->db->placehold("SELECT * FROM __purchases WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + return $this->db->result(); + } + + public function get_purchases($filter = array()) + { + $order_id_filter = ''; + if (!empty($filter['order_id'])) { + $order_id_filter = $this->db->placehold('AND order_id in(?@)', (array)$filter['order_id']); + } + + $query = $this->db->placehold("SELECT * FROM __purchases WHERE 1 $order_id_filter ORDER BY id"); + $this->db->query($query); + return $this->db->results(); + } + + public function update_purchase($id, $purchase) + { + $purchase = (object)$purchase; + $old_purchase = $this->get_purchase($id); + if (!$old_purchase) { + return false; + } + + $order = $this->get_order(intval($old_purchase->order_id)); + if (!$order) { + return false; + } + + // Не допустить нехватки на складе + $variant = $this->variants->get_variant($purchase->variant_id); + if ($order->closed && !empty($purchase->amount) && !empty($variant) && !$variant->infinity && $variant->stock<($purchase->amount-$old_purchase->amount)) { + return false; + } + + // Если заказ закрыт, нужно обновить склад при изменении покупки + if ($order->closed && !empty($purchase->amount)) { + if ($old_purchase->variant_id != $purchase->variant_id) { + if (!empty($old_purchase->variant_id)) { + $query = $this->db->placehold("UPDATE __variants SET stock=stock+? WHERE id=? AND stock IS NOT NULL LIMIT 1", $old_purchase->amount, $old_purchase->variant_id); + $this->db->query($query); + } + if (!empty($purchase->variant_id)) { + $query = $this->db->placehold("UPDATE __variants SET stock=stock-? WHERE id=? AND stock IS NOT NULL LIMIT 1", $purchase->amount, $purchase->variant_id); + $this->db->query($query); + } + } elseif (!empty($purchase->variant_id)) { + $query = $this->db->placehold("UPDATE __variants SET stock=stock+(?) WHERE id=? AND stock IS NOT NULL LIMIT 1", $old_purchase->amount - $purchase->amount, $purchase->variant_id); + $this->db->query($query); + } + } + + $query = $this->db->placehold("UPDATE __purchases SET ?% WHERE id=? LIMIT 1", $purchase, intval($id)); + $this->db->query($query); + $this->update_total_price($order->id); + return $id; + } + + public function add_purchase($purchase) + { + $purchase = (object)$purchase; + if (!empty($purchase->variant_id)) { + $variant = $this->variants->get_variant($purchase->variant_id); + if (empty($variant)) { + return false; + } + $product = $this->products->get_product(intval($variant->product_id)); + if (empty($product)) { + return false; + } + } + + $order = $this->get_order(intval($purchase->order_id)); + if (empty($order)) { + return false; + } + + // Не допустить нехватки на складе + if ($order->closed && !empty($purchase->amount) && !$variant->infinity && $variant->stock<$purchase->amount) { + return false; + } + + if (!isset($purchase->product_id) && isset($variant)) { + $purchase->product_id = $variant->product_id; + } + + if (!isset($purchase->product_name) && !empty($product)) { + $purchase->product_name = $product->name; + } + + if (!isset($purchase->sku) && !empty($variant)) { + $purchase->sku = $variant->sku; + } + + if (!isset($purchase->variant_name) && !empty($variant)) { + $purchase->variant_name = $variant->name; + } + + if (!isset($purchase->price) && !empty($variant)) { + $purchase->price = $variant->price; + } + + if (!isset($purchase->amount)) { + $purchase->amount = 1; + } + + // Если заказ закрыт, нужно обновить склад при добавлении покупки + if ($order->closed && !empty($purchase->amount) && !empty($variant->id)) { + $stock_diff = $purchase->amount; + $query = $this->db->placehold("UPDATE __variants SET stock=stock-? WHERE id=? AND stock IS NOT NULL LIMIT 1", $stock_diff, $variant->id); + $this->db->query($query); + } + + $query = $this->db->placehold("INSERT INTO __purchases SET ?%", $purchase); + $this->db->query($query); + $purchase_id = $this->db->insert_id(); + + $this->update_total_price($order->id); + return $purchase_id; + } + + public function delete_purchase($id) + { + $purchase = $this->get_purchase($id); + if (!$purchase) { + return false; + } + + $order = $this->get_order(intval($purchase->order_id)); + if (!$order) { + return false; + } + + // Если заказ закрыт, нужно обновить склад при изменении покупки + if ($order->closed && !empty($purchase->amount)) { + $stock_diff = $purchase->amount; + $query = $this->db->placehold("UPDATE __variants SET stock=stock+? WHERE id=? AND stock IS NOT NULL LIMIT 1", $stock_diff, $purchase->variant_id); + $this->db->query($query); + } + + $query = $this->db->placehold("DELETE FROM __purchases WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + $this->update_total_price($order->id); + return true; + } + + + public function close($order_id) + { + $order = $this->get_order(intval($order_id)); + if (empty($order)) { + return false; + } + + if (!$order->closed) { + $variants_amounts = array(); + $purchases = $this->get_purchases(array('order_id'=>$order->id)); + foreach ($purchases as $purchase) { + if (isset($variants_amounts[$purchase->variant_id])) { + $variants_amounts[$purchase->variant_id] += $purchase->amount; + } else { + $variants_amounts[$purchase->variant_id] = $purchase->amount; + } + } + + foreach ($variants_amounts as $id=>$amount) { + $variant = $this->variants->get_variant($id); + if (empty($variant) || ($variant->stock<$amount)) { + return false; + } + } + foreach ($purchases as $purchase) { + $variant = $this->variants->get_variant($purchase->variant_id); + if (!$variant->infinity) { + $new_stock = $variant->stock-$purchase->amount; + $this->variants->update_variant($variant->id, array('stock'=>$new_stock)); + } + } + $query = $this->db->placehold("UPDATE __orders SET closed=1, modified=NOW() WHERE id=? LIMIT 1", $order->id); + $this->db->query($query); + } + return $order->id; + } + + public function open($order_id) + { + $order = $this->get_order(intval($order_id)); + if (empty($order)) { + return false; + } + + if ($order->closed) { + $purchases = $this->get_purchases(array('order_id'=>$order->id)); + foreach ($purchases as $purchase) { + $variant = $this->variants->get_variant($purchase->variant_id); + if ($variant && !$variant->infinity) { + $new_stock = $variant->stock+$purchase->amount; + $this->variants->update_variant($variant->id, array('stock'=>$new_stock)); + } + } + $query = $this->db->placehold("UPDATE __orders SET closed=0, modified=NOW() WHERE id=? LIMIT 1", $order->id); + $this->db->query($query); + } + return $order->id; + } + + public function pay($order_id) + { + $order = $this->get_order(intval($order_id)); + if (empty($order)) { + return false; + } + + if (!$this->close($order->id)) { + return false; + } + $query = $this->db->placehold("UPDATE __orders SET payment_status=1, payment_date=NOW(), modified=NOW() WHERE id=? LIMIT 1", $order->id); + $this->db->query($query); + return $order->id; + } + + private function update_total_price($order_id) + { + $order = $this->get_order(intval($order_id)); + if (empty($order)) { + return false; + } + + $query = $this->db->placehold("UPDATE __orders o SET o.total_price=IFNULL((SELECT SUM(p.price*p.amount)*(100-o.discount)/100 FROM __purchases p WHERE p.order_id=o.id), 0)+o.delivery_price*(1-o.separate_delivery)-o.coupon_discount, modified=NOW() WHERE o.id=? LIMIT 1", $order->id); + $this->db->query($query); + return $order->id; + } + + + public function get_next_order($id, $status = null) + { + $f = ''; + if ($status!==null) { + $f = $this->db->placehold('AND status=?', $status); + } + $this->db->query("SELECT MIN(id) as id FROM __orders WHERE id>? $f LIMIT 1", $id); + $next_id = $this->db->result('id'); + if ($next_id) { + return $this->get_order(intval($next_id)); + } else { + return false; + } + } + + public function get_prev_order($id, $status = null) + { + $f = ''; + if ($status !== null) { + $f = $this->db->placehold('AND status=?', $status); + } + $this->db->query("SELECT MAX(id) as id FROM __orders WHERE iddb->result('id'); + if ($prev_id) { + return $this->get_order(intval($prev_id)); + } else { + return false; + } + } } diff --git a/api/Pages.php b/api/Pages.php index 66dee12..5192ae0 100755 --- a/api/Pages.php +++ b/api/Pages.php @@ -15,126 +15,132 @@ class Pages extends Simpla { - /* - * - * Функция возвращает страницу по ее id или url (в зависимости от типа) - * @param $id id или url страницы - * - */ - public function get_page($id) - { - if(gettype($id) == 'string') - $where = $this->db->placehold(' WHERE url=? ', $id); - else - $where = $this->db->placehold(' WHERE id=? ', intval($id)); - - $query = "SELECT id, url, header, name, meta_title, meta_description, meta_keywords, body, menu_id, position, visible + /* + * + * Функция возвращает страницу по ее id или url (в зависимости от типа) + * @param $id id или url страницы + * + */ + public function get_page($id) + { + if (gettype($id) == 'string') { + $where = $this->db->placehold(' WHERE url=? ', $id); + } else { + $where = $this->db->placehold(' WHERE id=? ', intval($id)); + } + + $query = "SELECT id, url, header, name, meta_title, meta_description, meta_keywords, body, menu_id, position, visible FROM __pages $where LIMIT 1"; - $this->db->query($query); - return $this->db->result(); - } - - /* - * - * Функция возвращает массив страниц, удовлетворяющих фильтру - * @param $filter - * - */ - public function get_pages($filter = array()) - { - $menu_filter = ''; - $visible_filter = ''; - $pages = array(); - - if(isset($filter['menu_id'])) - $menu_filter = $this->db->placehold('AND menu_id in (?@)', (array)$filter['menu_id']); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('AND visible = ?', intval($filter['visible'])); - - $query = "SELECT id, url, header, name, meta_title, meta_description, meta_keywords, body, menu_id, position, visible + $this->db->query($query); + return $this->db->result(); + } + + /* + * + * Функция возвращает массив страниц, удовлетворяющих фильтру + * @param $filter + * + */ + public function get_pages($filter = array()) + { + $menu_filter = ''; + $visible_filter = ''; + $pages = array(); + + if (isset($filter['menu_id'])) { + $menu_filter = $this->db->placehold('AND menu_id in (?@)', (array)$filter['menu_id']); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('AND visible = ?', intval($filter['visible'])); + } + + $query = "SELECT id, url, header, name, meta_title, meta_description, meta_keywords, body, menu_id, position, visible FROM __pages WHERE 1 $menu_filter $visible_filter ORDER BY position"; - $this->db->query($query); - - foreach($this->db->results() as $page) - $pages[$page->id] = $page; - - return $pages; - } - - /* - * - * Создание страницы - * - */ - public function add_page($page) - { - $query = $this->db->placehold('INSERT INTO __pages SET ?%', $page); - if(!$this->db->query($query)) - return false; - - $id = $this->db->insert_id(); - $this->db->query("UPDATE __pages SET position=id WHERE id=?", $id); - return $id; - } - - /* - * - * Обновить страницу - * - */ - public function update_page($id, $page) - { - $query = $this->db->placehold('UPDATE __pages SET ?% WHERE id in (?@)', $page, (array)$id); - if(!$this->db->query($query)) - return false; - return $id; - } - - /* - * - * Удалить страницу - * - */ - public function delete_page($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("DELETE FROM __pages WHERE id=? LIMIT 1", intval($id)); - if($this->db->query($query)) - return true; - } - return false; - } - - /* - * - * Функция возвращает массив меню - * - */ - public function get_menus() - { - $menus = array(); - $query = "SELECT * FROM __menu ORDER BY position"; - $this->db->query($query); - foreach($this->db->results() as $menu) - $menus[$menu->id] = $menu; - return $menus; - } - - /* - * - * Функция возвращает меню по id - * @param $id - * - */ - public function get_menu($menu_id) - { - $query = $this->db->placehold("SELECT * FROM __menu WHERE id=? LIMIT 1", intval($menu_id)); - $this->db->query($query); - return $this->db->result(); - } - + $this->db->query($query); + + foreach ($this->db->results() as $page) { + $pages[$page->id] = $page; + } + + return $pages; + } + + /* + * + * Создание страницы + * + */ + public function add_page($page) + { + $query = $this->db->placehold('INSERT INTO __pages SET ?%', $page); + if (!$this->db->query($query)) { + return false; + } + + $id = $this->db->insert_id(); + $this->db->query("UPDATE __pages SET position=id WHERE id=?", $id); + return $id; + } + + /* + * + * Обновить страницу + * + */ + public function update_page($id, $page) + { + $query = $this->db->placehold('UPDATE __pages SET ?% WHERE id in (?@)', $page, (array)$id); + if (!$this->db->query($query)) { + return false; + } + return $id; + } + + /* + * + * Удалить страницу + * + */ + public function delete_page($id) + { + if (!empty($id)) { + $query = $this->db->placehold("DELETE FROM __pages WHERE id=? LIMIT 1", intval($id)); + if ($this->db->query($query)) { + return true; + } + } + return false; + } + + /* + * + * Функция возвращает массив меню + * + */ + public function get_menus() + { + $menus = array(); + $query = "SELECT * FROM __menu ORDER BY position"; + $this->db->query($query); + foreach ($this->db->results() as $menu) { + $menus[$menu->id] = $menu; + } + return $menus; + } + + /* + * + * Функция возвращает меню по id + * @param $id + * + */ + public function get_menu($menu_id) + { + $query = $this->db->placehold("SELECT * FROM __menu WHERE id=? LIMIT 1", intval($menu_id)); + $this->db->query($query); + return $this->db->result(); + } } diff --git a/api/Payment.php b/api/Payment.php index 6700f40..94fad0a 100755 --- a/api/Payment.php +++ b/api/Payment.php @@ -14,153 +14,146 @@ class Payment extends Simpla { - public function get_payment_methods($filter = array()) - { - $delivery_filter = ''; - if(!empty($filter['delivery_id'])) - $delivery_filter = $this->db->placehold('AND id in (SELECT payment_method_id FROM __delivery_payment dp WHERE dp.delivery_id=?)', intval($filter['delivery_id'])); - - $enabled_filter = ''; - if(!empty($filter['enabled'])) - $enabled_filter = $this->db->placehold('AND enabled=?', intval($filter['enabled'])); - - $query = "SELECT * + public function get_payment_methods($filter = array()) + { + $delivery_filter = ''; + if (!empty($filter['delivery_id'])) { + $delivery_filter = $this->db->placehold('AND id in (SELECT payment_method_id FROM __delivery_payment dp WHERE dp.delivery_id=?)', intval($filter['delivery_id'])); + } + + $enabled_filter = ''; + if (!empty($filter['enabled'])) { + $enabled_filter = $this->db->placehold('AND enabled=?', intval($filter['enabled'])); + } + + $query = "SELECT * FROM __payment_methods WHERE 1 $delivery_filter $enabled_filter ORDER BY position"; - $this->db->query($query); - return $this->db->results(); - } - - public function get_payment_method($id) - { - $query = $this->db->placehold("SELECT * FROM __payment_methods WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - $payment_method = $this->db->result(); - - return $payment_method; - } - - public function get_payment_settings($method_id) - { - $query = $this->db->placehold("SELECT settings FROM __payment_methods WHERE id=? LIMIT 1", intval($method_id)); - $this->db->query($query); - $settings = $this->db->result('settings'); - - $settings = unserialize($settings); - - return $settings; - } - - public function get_payment_modules() - { - $modules_dir = $this->config->root_dir.'payment/'; - - $modules = array(); - $handler = opendir($modules_dir); - while ($dir = readdir($handler)) - { - $dir = preg_replace("/[^A-Za-z0-9]+/", "", $dir); - if (!empty($dir) && $dir != "." && $dir != ".." && is_dir($modules_dir.$dir)) - { - - if(is_readable($modules_dir.$dir.'/settings.xml') && $xml = simplexml_load_file($modules_dir.$dir.'/settings.xml')) - { - $module = new stdClass; - - $module->name = (string)$xml->name; - $module->settings = array(); - - foreach($xml->settings as $setting) - { - $module->settings[(string)$setting->variable] = new stdClass; - $module->settings[(string)$setting->variable]->name = (string)$setting->name; - $module->settings[(string)$setting->variable]->variable = (string)$setting->variable; - $module->settings[(string)$setting->variable]->variable_options = array(); - foreach($setting->options as $option) - { - $module->settings[(string)$setting->variable]->options[(string)$option->value] = new stdClass; - $module->settings[(string)$setting->variable]->options[(string)$option->value]->name = (string)$option->name; - $module->settings[(string)$setting->variable]->options[(string)$option->value]->value = (string)$option->value; - } - } - $modules[$dir] = $module; - } - - } - } - closedir($handler); - return $modules; - - } - - public function get_payment_deliveries($id) - { - $query = $this->db->placehold("SELECT delivery_id FROM __delivery_payment WHERE payment_method_id=?", intval($id)); - $this->db->query($query); - - return $this->db->results('delivery_id'); - } - - public function update_payment_method($id, $payment_method) - { - $query = $this->db->placehold("UPDATE __payment_methods SET ?% WHERE id in(?@)", $payment_method, (array)$id); - $this->db->query($query); - - return $id; - } - - public function update_payment_settings($method_id, $settings) - { - if(!is_string($settings)) - { - $settings = serialize($settings); - } - $query = $this->db->placehold("UPDATE __payment_methods SET settings=? WHERE id in(?@) LIMIT 1", $settings, (array)$method_id); - $this->db->query($query); - - return $method_id; - } - - public function update_payment_deliveries($id, $deliveries_ids) - { - $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE payment_method_id=?", intval($id)); - $this->db->query($query); - if(is_array($deliveries_ids)) - foreach($deliveries_ids as $d_id) - $this->db->query("INSERT INTO __delivery_payment SET payment_method_id=?, delivery_id=?", $id, $d_id); - } - - public function add_payment_method($payment_method) - { - $query = $this->db->placehold('INSERT INTO __payment_methods + $this->db->query($query); + return $this->db->results(); + } + + public function get_payment_method($id) + { + $query = $this->db->placehold("SELECT * FROM __payment_methods WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + $payment_method = $this->db->result(); + + return $payment_method; + } + + public function get_payment_settings($method_id) + { + $query = $this->db->placehold("SELECT settings FROM __payment_methods WHERE id=? LIMIT 1", intval($method_id)); + $this->db->query($query); + $settings = $this->db->result('settings'); + + $settings = unserialize($settings); + + return $settings; + } + + public function get_payment_modules() + { + $modules_dir = $this->config->root_dir.'payment/'; + + $modules = array(); + $handler = opendir($modules_dir); + while ($dir = readdir($handler)) { + $dir = preg_replace("/[^A-Za-z0-9]+/", "", $dir); + if (!empty($dir) && $dir != "." && $dir != ".." && is_dir($modules_dir.$dir)) { + if (is_readable($modules_dir.$dir.'/settings.xml') && $xml = simplexml_load_file($modules_dir.$dir.'/settings.xml')) { + $module = new stdClass; + + $module->name = (string)$xml->name; + $module->settings = array(); + + foreach ($xml->settings as $setting) { + $module->settings[(string)$setting->variable] = new stdClass; + $module->settings[(string)$setting->variable]->name = (string)$setting->name; + $module->settings[(string)$setting->variable]->variable = (string)$setting->variable; + $module->settings[(string)$setting->variable]->variable_options = array(); + foreach ($setting->options as $option) { + $module->settings[(string)$setting->variable]->options[(string)$option->value] = new stdClass; + $module->settings[(string)$setting->variable]->options[(string)$option->value]->name = (string)$option->name; + $module->settings[(string)$setting->variable]->options[(string)$option->value]->value = (string)$option->value; + } + } + $modules[$dir] = $module; + } + } + } + closedir($handler); + return $modules; + } + + public function get_payment_deliveries($id) + { + $query = $this->db->placehold("SELECT delivery_id FROM __delivery_payment WHERE payment_method_id=?", intval($id)); + $this->db->query($query); + + return $this->db->results('delivery_id'); + } + + public function update_payment_method($id, $payment_method) + { + $query = $this->db->placehold("UPDATE __payment_methods SET ?% WHERE id in(?@)", $payment_method, (array)$id); + $this->db->query($query); + + return $id; + } + + public function update_payment_settings($method_id, $settings) + { + if (!is_string($settings)) { + $settings = serialize($settings); + } + $query = $this->db->placehold("UPDATE __payment_methods SET settings=? WHERE id in(?@) LIMIT 1", $settings, (array)$method_id); + $this->db->query($query); + + return $method_id; + } + + public function update_payment_deliveries($id, $deliveries_ids) + { + $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE payment_method_id=?", intval($id)); + $this->db->query($query); + if (is_array($deliveries_ids)) { + foreach ($deliveries_ids as $d_id) { + $this->db->query("INSERT INTO __delivery_payment SET payment_method_id=?, delivery_id=?", $id, $d_id); + } + } + } + + public function add_payment_method($payment_method) + { + $query = $this->db->placehold('INSERT INTO __payment_methods SET ?%', - $payment_method); - - if(!$this->db->query($query)) - return false; - - $id = $this->db->insert_id(); - $this->db->query("UPDATE __payment_methods SET position=id WHERE id=?", $id); + $payment_method); - return $id; - } + if (!$this->db->query($query)) { + return false; + } - public function delete_payment_method($id) - { - if(!empty($id)) - { - // Удаляем связь метода оплаты с достаками - $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE payment_method_id=?", intval($id)); - $this->db->query($query); + $id = $this->db->insert_id(); + $this->db->query("UPDATE __payment_methods SET position=id WHERE id=?", $id); - $query = $this->db->placehold("DELETE FROM __payment_methods WHERE id=? LIMIT 1", intval($id)); - $this->db->query($query); - } - } + return $id; + } + public function delete_payment_method($id) + { + if (!empty($id)) { + // Удаляем связь метода оплаты с достаками + $query = $this->db->placehold("DELETE FROM __delivery_payment WHERE payment_method_id=?", intval($id)); + $this->db->query($query); + $query = $this->db->placehold("DELETE FROM __payment_methods WHERE id=? LIMIT 1", intval($id)); + $this->db->query($query); + } + } } diff --git a/api/Products.php b/api/Products.php index 75265b4..c04588c 100755 --- a/api/Products.php +++ b/api/Products.php @@ -13,101 +13,109 @@ class Products extends Simpla { - /** - * Функция возвращает товары - * Возможные значения фильтра: - * id - id товара или их массив - * category_id - id категории или их массив - * brand_id - id бренда или их массив - * page - текущая страница, integer - * limit - количество товаров на странице, integer - * sort - порядок товаров, возможные значения: position(по умолчанию), name, price - * keyword - ключевое слово для поиска - * features - фильтр по свойствам товара, массив (id свойства => значение свойства) - */ - public function get_products($filter = array()) - { - // По умолчанию - $limit = 100; - $page = 1; - $category_id_filter = ''; - $brand_id_filter = ''; - $product_id_filter = ''; - $features_filter = ''; - $keyword_filter = ''; - $visible_filter = ''; - $is_featured_filter = ''; - $discounted_filter = ''; - $in_stock_filter = ''; - $group_by = ''; - $order = 'p.position DESC'; - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - - if(!empty($filter['id'])) - $product_id_filter = $this->db->placehold('AND p.id in(?@)', (array)$filter['id']); - - if(!empty($filter['category_id'])) - { - $category_id_filter = $this->db->placehold('INNER JOIN __products_categories pc ON pc.product_id = p.id AND pc.category_id in(?@)', (array)$filter['category_id']); - $group_by = "GROUP BY p.id"; - } - - if(!empty($filter['brand_id'])) - $brand_id_filter = $this->db->placehold('AND p.brand_id in(?@)', (array)$filter['brand_id']); - - if(isset($filter['featured'])) - $is_featured_filter = $this->db->placehold('AND p.featured=?', intval($filter['featured'])); - - if(isset($filter['discounted'])) - $discounted_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.compare_price>0 LIMIT 1) = ?', intval($filter['discounted'])); - - if(isset($filter['in_stock'])) - $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('AND p.visible=?', intval($filter['visible'])); - - if(!empty($filter['sort'])) - switch ($filter['sort']) - { - case 'position': - $order = 'p.position DESC'; - break; - case 'name': - $order = 'p.name'; - break; - case 'created': - $order = 'p.created DESC'; - break; - case 'price': - //$order = 'pv.price IS NULL, pv.price=0, pv.price'; - $order = '(SELECT -pv.price FROM __variants pv WHERE (pv.stock IS NULL OR pv.stock>0) AND p.id = pv.product_id AND pv.position=(SELECT MIN(position) FROM __variants WHERE (stock>0 OR stock IS NULL) AND product_id=p.id LIMIT 1) LIMIT 1) DESC'; - break; - } - - if(!empty($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - { - $kw = $this->db->escape(trim($keyword)); - if($kw!=='') - $keyword_filter .= $this->db->placehold("AND (p.name LIKE '%$kw%' OR p.meta_keywords LIKE '%$kw%' OR p.id in (SELECT product_id FROM __variants WHERE sku LIKE '%$kw%'))"); - } - } - - if(!empty($filter['features']) && !empty($filter['features'])) - foreach($filter['features'] as $feature=>$value) - $features_filter .= $this->db->placehold('AND p.id in (SELECT product_id FROM __options WHERE feature_id=? AND value=? ) ', $feature, $value); - - $query = "SELECT + /** + * Функция возвращает товары + * Возможные значения фильтра: + * id - id товара или их массив + * category_id - id категории или их массив + * brand_id - id бренда или их массив + * page - текущая страница, integer + * limit - количество товаров на странице, integer + * sort - порядок товаров, возможные значения: position(по умолчанию), name, price + * keyword - ключевое слово для поиска + * features - фильтр по свойствам товара, массив (id свойства => значение свойства) + */ + public function get_products($filter = array()) + { + // По умолчанию + $limit = 100; + $page = 1; + $category_id_filter = ''; + $brand_id_filter = ''; + $product_id_filter = ''; + $features_filter = ''; + $keyword_filter = ''; + $visible_filter = ''; + $is_featured_filter = ''; + $discounted_filter = ''; + $in_stock_filter = ''; + $group_by = ''; + $order = 'p.position DESC'; + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + + if (!empty($filter['id'])) { + $product_id_filter = $this->db->placehold('AND p.id in(?@)', (array)$filter['id']); + } + + if (!empty($filter['category_id'])) { + $category_id_filter = $this->db->placehold('INNER JOIN __products_categories pc ON pc.product_id = p.id AND pc.category_id in(?@)', (array)$filter['category_id']); + $group_by = "GROUP BY p.id"; + } + + if (!empty($filter['brand_id'])) { + $brand_id_filter = $this->db->placehold('AND p.brand_id in(?@)', (array)$filter['brand_id']); + } + + if (isset($filter['featured'])) { + $is_featured_filter = $this->db->placehold('AND p.featured=?', intval($filter['featured'])); + } + + if (isset($filter['discounted'])) { + $discounted_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.compare_price>0 LIMIT 1) = ?', intval($filter['discounted'])); + } + + if (isset($filter['in_stock'])) { + $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('AND p.visible=?', intval($filter['visible'])); + } + + if (!empty($filter['sort'])) { + switch ($filter['sort']) { + case 'position': + $order = 'p.position DESC'; + break; + case 'name': + $order = 'p.name'; + break; + case 'created': + $order = 'p.created DESC'; + break; + case 'price': + //$order = 'pv.price IS NULL, pv.price=0, pv.price'; + $order = '(SELECT -pv.price FROM __variants pv WHERE (pv.stock IS NULL OR pv.stock>0) AND p.id = pv.product_id AND pv.position=(SELECT MIN(position) FROM __variants WHERE (stock>0 OR stock IS NULL) AND product_id=p.id LIMIT 1) LIMIT 1) DESC'; + break; + } + } + + if (!empty($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $kw = $this->db->escape(trim($keyword)); + if ($kw!=='') { + $keyword_filter .= $this->db->placehold("AND (p.name LIKE '%$kw%' OR p.meta_keywords LIKE '%$kw%' OR p.id in (SELECT product_id FROM __variants WHERE sku LIKE '%$kw%'))"); + } + } + } + + if (!empty($filter['features']) && !empty($filter['features'])) { + foreach ($filter['features'] as $feature=>$value) { + $features_filter .= $this->db->placehold('AND p.id in (SELECT product_id FROM __options WHERE feature_id=? AND value=? ) ', $feature, $value); + } + } + + $query = "SELECT p.id, p.url, p.brand_id, @@ -140,69 +148,77 @@ public function get_products($filter = array()) ORDER BY $order $sql_limit"; - $this->db->query($query); - - return $this->db->results(); - } - - /** - * Функция возвращает количество товаров - * Возможные значения фильтра: - * category_id - id категории или их массив - * brand_id - id бренда или их массив - * keyword - ключевое слово для поиска - * features - фильтр по свойствам товара, массив (id свойства => значение свойства) - */ - public function count_products($filter = array()) - { - $category_id_filter = ''; - $brand_id_filter = ''; - $product_id_filter = ''; - $keyword_filter = ''; - $visible_filter = ''; - $is_featured_filter = ''; - $in_stock_filter = ''; - $discounted_filter = ''; - $features_filter = ''; - - if(!empty($filter['category_id'])) - $category_id_filter = $this->db->placehold('INNER JOIN __products_categories pc ON pc.product_id = p.id AND pc.category_id in(?@)', (array)$filter['category_id']); - - if(!empty($filter['brand_id'])) - $brand_id_filter = $this->db->placehold('AND p.brand_id in(?@)', (array)$filter['brand_id']); - - if(!empty($filter['id'])) - $product_id_filter = $this->db->placehold('AND p.id in(?@)', (array)$filter['id']); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - { - $kw = $this->db->escape(trim($keyword)); - if($kw!=='') - $keyword_filter .= $this->db->placehold("AND (p.name LIKE '%$kw%' OR p.meta_keywords LIKE '%$kw%' OR p.id in (SELECT product_id FROM __variants WHERE sku LIKE '%$kw%'))"); - } - } - - if(isset($filter['featured'])) - $is_featured_filter = $this->db->placehold('AND p.featured=?', intval($filter['featured'])); - - if(isset($filter['in_stock'])) - $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); - - if(isset($filter['discounted'])) - $discounted_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.compare_price>0 LIMIT 1) = ?', intval($filter['discounted'])); - - if(isset($filter['visible'])) - $visible_filter = $this->db->placehold('AND p.visible=?', intval($filter['visible'])); - - - if(!empty($filter['features']) && !empty($filter['features'])) - foreach($filter['features'] as $feature=>$value) - $features_filter .= $this->db->placehold('AND p.id in (SELECT product_id FROM __options WHERE feature_id=? AND value=? ) ', $feature, $value); - - $query = "SELECT count(distinct p.id) as count + $this->db->query($query); + + return $this->db->results(); + } + + /** + * Функция возвращает количество товаров + * Возможные значения фильтра: + * category_id - id категории или их массив + * brand_id - id бренда или их массив + * keyword - ключевое слово для поиска + * features - фильтр по свойствам товара, массив (id свойства => значение свойства) + */ + public function count_products($filter = array()) + { + $category_id_filter = ''; + $brand_id_filter = ''; + $product_id_filter = ''; + $keyword_filter = ''; + $visible_filter = ''; + $is_featured_filter = ''; + $in_stock_filter = ''; + $discounted_filter = ''; + $features_filter = ''; + + if (!empty($filter['category_id'])) { + $category_id_filter = $this->db->placehold('INNER JOIN __products_categories pc ON pc.product_id = p.id AND pc.category_id in(?@)', (array)$filter['category_id']); + } + + if (!empty($filter['brand_id'])) { + $brand_id_filter = $this->db->placehold('AND p.brand_id in(?@)', (array)$filter['brand_id']); + } + + if (!empty($filter['id'])) { + $product_id_filter = $this->db->placehold('AND p.id in(?@)', (array)$filter['id']); + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $kw = $this->db->escape(trim($keyword)); + if ($kw!=='') { + $keyword_filter .= $this->db->placehold("AND (p.name LIKE '%$kw%' OR p.meta_keywords LIKE '%$kw%' OR p.id in (SELECT product_id FROM __variants WHERE sku LIKE '%$kw%'))"); + } + } + } + + if (isset($filter['featured'])) { + $is_featured_filter = $this->db->placehold('AND p.featured=?', intval($filter['featured'])); + } + + if (isset($filter['in_stock'])) { + $in_stock_filter = $this->db->placehold('AND (SELECT count(*)>0 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock'])); + } + + if (isset($filter['discounted'])) { + $discounted_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.compare_price>0 LIMIT 1) = ?', intval($filter['discounted'])); + } + + if (isset($filter['visible'])) { + $visible_filter = $this->db->placehold('AND p.visible=?', intval($filter['visible'])); + } + + + if (!empty($filter['features']) && !empty($filter['features'])) { + foreach ($filter['features'] as $feature=>$value) { + $features_filter .= $this->db->placehold('AND p.id in (SELECT product_id FROM __options WHERE feature_id=? AND value=? ) ', $feature, $value); + } + } + + $query = "SELECT count(distinct p.id) as count FROM __products AS p $category_id_filter WHERE 1 @@ -215,24 +231,25 @@ public function count_products($filter = array()) $visible_filter $features_filter "; - $this->db->query($query); - return $this->db->result('count'); - } - - - /** - * Функция возвращает товар по id - * @param $id - * @retval object - */ - public function get_product($id) - { - if(is_int($id)) - $filter = $this->db->placehold('p.id = ?', $id); - else - $filter = $this->db->placehold('p.url = ?', $id); - - $query = "SELECT DISTINCT + $this->db->query($query); + return $this->db->result('count'); + } + + + /** + * Функция возвращает товар по id + * @param $id + * @retval object + */ + public function get_product($id) + { + if (is_int($id)) { + $filter = $this->db->placehold('p.id = ?', $id); + } else { + $filter = $this->db->placehold('p.url = ?', $id); + } + + $query = "SELECT DISTINCT p.id, p.url, p.brand_id, @@ -250,165 +267,175 @@ public function get_product($id) WHERE $filter GROUP BY p.id LIMIT 1"; - $this->db->query($query); - $product = $this->db->result(); - return $product; - } - - public function update_product($id, $product) - { - $query = $this->db->placehold("UPDATE __products SET ?% WHERE id in (?@) LIMIT ?", $product, (array)$id, count((array)$id)); - if($this->db->query($query)) - return $id; - else - return false; - } - - public function add_product($product) - { - $product = (array) $product; - - if(empty($product['url'])) - { - $product['url'] = preg_replace("/[\s]+/ui", '-', $product['name']); - $product['url'] = strtolower(preg_replace("/[^0-9a-zа-я\-]+/ui", '', $product['url'])); - } - - // Если есть товар с таким URL, добавляем к нему число - while($this->get_product((string)$product['url'])) - { - if(preg_match('/(.+)_([0-9]+)$/', $product['url'], $parts)) - $product['url'] = $parts[1].'_'.($parts[2]+1); - else - $product['url'] = $product['url'].'_2'; - } - - if($this->db->query("INSERT INTO __products SET ?%", $product)) - { - $id = $this->db->insert_id(); - $this->db->query("UPDATE __products SET position=id WHERE id=?", $id); - return $id; - } - else - return false; - } - - - /* - * - * Удалить товар - * - */ - public function delete_product($id) - { - if(!empty($id)) - { - // Удаляем варианты - $variants = $this->variants->get_variants(array('product_id'=>$id)); - foreach($variants as $v) - $this->variants->delete_variant($v->id); - - // Удаляем изображения - $images = $this->get_images(array('product_id'=>$id)); - foreach($images as $i) - $this->delete_image($i->id); - - // Удаляем категории - $categories = $this->categories->get_categories(array('product_id'=>$id)); - foreach($categories as $c) - $this->categories->delete_product_category($id, $c->id); - - // Удаляем свойства - $options = $this->features->get_options(array('product_id'=>$id)); - foreach($options as $o) - $this->features->delete_option($id, $o->feature_id); - - // Удаляем связанные товары - $related = $this->get_related_products($id); - foreach($related as $r) - $this->delete_related_product($id, $r->related_id); - - // Удаляем товар из связанных с другими - $query = $this->db->placehold("DELETE FROM __related_products WHERE related_id=?", intval($id)); - $this->db->query($query); - - // Удаляем отзывы - $comments = $this->comments->get_comments(array('object_id'=>$id, 'type'=>'product')); - foreach($comments as $c) - $this->comments->delete_comment($c->id); - - // Удаляем из покупок - $this->db->query('UPDATE __purchases SET product_id=NULL WHERE product_id=?', intval($id)); - - // Удаляем товар - $query = $this->db->placehold("DELETE FROM __products WHERE id=? LIMIT 1", intval($id)); - if($this->db->query($query)) - return true; - } - return false; - } - - public function duplicate_product($id) - { - $product = $this->get_product($id); - $product->id = null; - $product->external_id = ''; - $product->created = null; - - // Сдвигаем товары вперед и вставляем копию на соседнюю позицию - $this->db->query('UPDATE __products SET position=position+1 WHERE position>?', $product->position); - $new_id = $this->products->add_product($product); - $this->db->query('UPDATE __products SET position=? WHERE id=?', $product->position+1, $new_id); - - // Очищаем url - $this->db->query('UPDATE __products SET url="" WHERE id=?', $new_id); - - // Дублируем категории - $categories = $this->categories->get_product_categories($id); - foreach($categories as $c) - $this->categories->add_product_category($new_id, $c->category_id); - - // Дублируем изображения - $images = $this->get_images(array('product_id'=>$id)); - foreach($images as $image) - $this->add_image($new_id, $image->filename); - - // Дублируем варианты - $variants = $this->variants->get_variants(array('product_id'=>$id)); - foreach($variants as $variant) - { - $variant->product_id = $new_id; - unset($variant->id); - if($variant->infinity) - $variant->stock = null; - unset($variant->infinity); - $variant->external_id = ''; - $this->variants->add_variant($variant); - } - - // Дублируем свойства - $options = $this->features->get_options(array('product_id'=>$id)); - foreach($options as $o) - $this->features->update_option($new_id, $o->feature_id, $o->value); - - // Дублируем связанные товары - $related = $this->get_related_products($id); - foreach($related as $r) - $this->add_related_product($new_id, $r->related_id); - - - return $new_id; - } - - - public function get_related_products($product_id = array()) - { - if(empty($product_id)) - return array(); - - $product_id_filter = $this->db->placehold('AND product_id in(?@)', (array)$product_id); - - $query = $this->db->placehold("SELECT product_id, related_id, position + $this->db->query($query); + $product = $this->db->result(); + return $product; + } + + public function update_product($id, $product) + { + $query = $this->db->placehold("UPDATE __products SET ?% WHERE id in (?@) LIMIT ?", $product, (array)$id, count((array)$id)); + if ($this->db->query($query)) { + return $id; + } else { + return false; + } + } + + public function add_product($product) + { + $product = (array) $product; + + if (empty($product['url'])) { + $product['url'] = preg_replace("/[\s]+/ui", '-', $product['name']); + $product['url'] = strtolower(preg_replace("/[^0-9a-zа-я\-]+/ui", '', $product['url'])); + } + + // Если есть товар с таким URL, добавляем к нему число + while ($this->get_product((string)$product['url'])) { + if (preg_match('/(.+)_([0-9]+)$/', $product['url'], $parts)) { + $product['url'] = $parts[1].'_'.($parts[2]+1); + } else { + $product['url'] = $product['url'].'_2'; + } + } + + if ($this->db->query("INSERT INTO __products SET ?%", $product)) { + $id = $this->db->insert_id(); + $this->db->query("UPDATE __products SET position=id WHERE id=?", $id); + return $id; + } else { + return false; + } + } + + + /* + * + * Удалить товар + * + */ + public function delete_product($id) + { + if (!empty($id)) { + // Удаляем варианты + $variants = $this->variants->get_variants(array('product_id'=>$id)); + foreach ($variants as $v) { + $this->variants->delete_variant($v->id); + } + + // Удаляем изображения + $images = $this->get_images(array('product_id'=>$id)); + foreach ($images as $i) { + $this->delete_image($i->id); + } + + // Удаляем категории + $categories = $this->categories->get_categories(array('product_id'=>$id)); + foreach ($categories as $c) { + $this->categories->delete_product_category($id, $c->id); + } + + // Удаляем свойства + $options = $this->features->get_options(array('product_id'=>$id)); + foreach ($options as $o) { + $this->features->delete_option($id, $o->feature_id); + } + + // Удаляем связанные товары + $related = $this->get_related_products($id); + foreach ($related as $r) { + $this->delete_related_product($id, $r->related_id); + } + + // Удаляем товар из связанных с другими + $query = $this->db->placehold("DELETE FROM __related_products WHERE related_id=?", intval($id)); + $this->db->query($query); + + // Удаляем отзывы + $comments = $this->comments->get_comments(array('object_id'=>$id, 'type'=>'product')); + foreach ($comments as $c) { + $this->comments->delete_comment($c->id); + } + + // Удаляем из покупок + $this->db->query('UPDATE __purchases SET product_id=NULL WHERE product_id=?', intval($id)); + + // Удаляем товар + $query = $this->db->placehold("DELETE FROM __products WHERE id=? LIMIT 1", intval($id)); + if ($this->db->query($query)) { + return true; + } + } + return false; + } + + public function duplicate_product($id) + { + $product = $this->get_product($id); + $product->id = null; + $product->external_id = ''; + $product->created = null; + + // Сдвигаем товары вперед и вставляем копию на соседнюю позицию + $this->db->query('UPDATE __products SET position=position+1 WHERE position>?', $product->position); + $new_id = $this->products->add_product($product); + $this->db->query('UPDATE __products SET position=? WHERE id=?', $product->position+1, $new_id); + + // Очищаем url + $this->db->query('UPDATE __products SET url="" WHERE id=?', $new_id); + + // Дублируем категории + $categories = $this->categories->get_product_categories($id); + foreach ($categories as $c) { + $this->categories->add_product_category($new_id, $c->category_id); + } + + // Дублируем изображения + $images = $this->get_images(array('product_id'=>$id)); + foreach ($images as $image) { + $this->add_image($new_id, $image->filename); + } + + // Дублируем варианты + $variants = $this->variants->get_variants(array('product_id'=>$id)); + foreach ($variants as $variant) { + $variant->product_id = $new_id; + unset($variant->id); + if ($variant->infinity) { + $variant->stock = null; + } + unset($variant->infinity); + $variant->external_id = ''; + $this->variants->add_variant($variant); + } + + // Дублируем свойства + $options = $this->features->get_options(array('product_id'=>$id)); + foreach ($options as $o) { + $this->features->update_option($new_id, $o->feature_id, $o->value); + } + + // Дублируем связанные товары + $related = $this->get_related_products($id); + foreach ($related as $r) { + $this->add_related_product($new_id, $r->related_id); + } + + + return $new_id; + } + + + public function get_related_products($product_id = array()) + { + if (empty($product_id)) { + return array(); + } + + $product_id_filter = $this->db->placehold('AND product_id in(?@)', (array)$product_id); + + $query = $this->db->placehold("SELECT product_id, related_id, position FROM __related_products WHERE 1 @@ -416,136 +443,134 @@ public function get_related_products($product_id = array()) ORDER BY position "); - $this->db->query($query); - return $this->db->results(); - } - - // Функция возвращает связанные товары - public function add_related_product($product_id, $related_id, $position=0) - { - $query = $this->db->placehold("INSERT IGNORE INTO __related_products SET product_id=?, related_id=?, position=?", $product_id, $related_id, $position); - $this->db->query($query); - return $related_id; - } - - // Удаление связанного товара - public function delete_related_product($product_id, $related_id) - { - $query = $this->db->placehold("DELETE FROM __related_products WHERE product_id=? AND related_id=? LIMIT 1", intval($product_id), intval($related_id)); - $this->db->query($query); - } - - - public function get_images($filter = array()) - { - $product_id_filter = ''; - $group_by = ''; - - if(!empty($filter['product_id'])) - $product_id_filter = $this->db->placehold('AND i.product_id in(?@)', (array)$filter['product_id']); - - // images - $query = $this->db->placehold("SELECT i.id, i.product_id, i.name, i.filename, i.position + $this->db->query($query); + return $this->db->results(); + } + + // Функция возвращает связанные товары + public function add_related_product($product_id, $related_id, $position=0) + { + $query = $this->db->placehold("INSERT IGNORE INTO __related_products SET product_id=?, related_id=?, position=?", $product_id, $related_id, $position); + $this->db->query($query); + return $related_id; + } + + // Удаление связанного товара + public function delete_related_product($product_id, $related_id) + { + $query = $this->db->placehold("DELETE FROM __related_products WHERE product_id=? AND related_id=? LIMIT 1", intval($product_id), intval($related_id)); + $this->db->query($query); + } + + + public function get_images($filter = array()) + { + $product_id_filter = ''; + $group_by = ''; + + if (!empty($filter['product_id'])) { + $product_id_filter = $this->db->placehold('AND i.product_id in(?@)', (array)$filter['product_id']); + } + + // images + $query = $this->db->placehold("SELECT i.id, i.product_id, i.name, i.filename, i.position FROM __images AS i WHERE 1 $product_id_filter $group_by ORDER BY i.product_id, i.position"); - $this->db->query($query); - return $this->db->results(); - } - - public function add_image($product_id, $filename, $name = '') - { - $query = $this->db->placehold("SELECT id FROM __images WHERE product_id=? AND filename=?", $product_id, $filename); - $this->db->query($query); - $id = $this->db->result('id'); - if(empty($id)) - { - $query = $this->db->placehold("INSERT INTO __images SET product_id=?, filename=?", $product_id, $filename); - $this->db->query($query); - $id = $this->db->insert_id(); - $query = $this->db->placehold("UPDATE __images SET position=id WHERE id=?", $id); - $this->db->query($query); - } - return($id); - } - - public function update_image($id, $image) - { - - $query = $this->db->placehold("UPDATE __images SET ?% WHERE id=?", $image, $id); - $this->db->query($query); - - return($id); - } - - public function delete_image($id) - { - $query = $this->db->placehold("SELECT filename FROM __images WHERE id=?", $id); - $this->db->query($query); - $filename = $this->db->result('filename'); - $query = $this->db->placehold("DELETE FROM __images WHERE id=? LIMIT 1", $id); - $this->db->query($query); - $query = $this->db->placehold("SELECT count(*) as count FROM __images WHERE filename=? LIMIT 1", $filename); - $this->db->query($query); - $count = $this->db->result('count'); - if($count == 0) - { - $file = pathinfo($filename, PATHINFO_FILENAME); - $ext = pathinfo($filename, PATHINFO_EXTENSION); - - // Удалить все ресайзы - $rezised_images = glob($this->config->root_dir.$this->config->resized_images_dir.$file.".*x*.".$ext); - if(is_array($rezised_images)) - foreach (glob($this->config->root_dir.$this->config->resized_images_dir.$file.".*x*.".$ext) as $f) - @unlink($f); - - @unlink($this->config->root_dir.$this->config->original_images_dir.$filename); - } - } - - /* - * - * Следующий товар - * - */ - public function get_next_product($id) - { - $this->db->query("SELECT position FROM __products WHERE id=? LIMIT 1", $id); - $position = $this->db->result('position'); - - $this->db->query("SELECT pc.category_id FROM __products_categories pc WHERE product_id=? ORDER BY position LIMIT 1", $id); - $category_id = $this->db->result('category_id'); - - $query = $this->db->placehold("SELECT id FROM __products p, __products_categories pc + $this->db->query($query); + return $this->db->results(); + } + + public function add_image($product_id, $filename, $name = '') + { + $query = $this->db->placehold("SELECT id FROM __images WHERE product_id=? AND filename=?", $product_id, $filename); + $this->db->query($query); + $id = $this->db->result('id'); + if (empty($id)) { + $query = $this->db->placehold("INSERT INTO __images SET product_id=?, filename=?", $product_id, $filename); + $this->db->query($query); + $id = $this->db->insert_id(); + $query = $this->db->placehold("UPDATE __images SET position=id WHERE id=?", $id); + $this->db->query($query); + } + return($id); + } + + public function update_image($id, $image) + { + $query = $this->db->placehold("UPDATE __images SET ?% WHERE id=?", $image, $id); + $this->db->query($query); + + return($id); + } + + public function delete_image($id) + { + $query = $this->db->placehold("SELECT filename FROM __images WHERE id=?", $id); + $this->db->query($query); + $filename = $this->db->result('filename'); + $query = $this->db->placehold("DELETE FROM __images WHERE id=? LIMIT 1", $id); + $this->db->query($query); + $query = $this->db->placehold("SELECT count(*) as count FROM __images WHERE filename=? LIMIT 1", $filename); + $this->db->query($query); + $count = $this->db->result('count'); + if ($count == 0) { + $file = pathinfo($filename, PATHINFO_FILENAME); + $ext = pathinfo($filename, PATHINFO_EXTENSION); + + // Удалить все ресайзы + $rezised_images = glob($this->config->root_dir.$this->config->resized_images_dir.$file.".*x*.".$ext); + if (is_array($rezised_images)) { + foreach (glob($this->config->root_dir.$this->config->resized_images_dir.$file.".*x*.".$ext) as $f) { + @unlink($f); + } + } + + @unlink($this->config->root_dir.$this->config->original_images_dir.$filename); + } + } + + /* + * + * Следующий товар + * + */ + public function get_next_product($id) + { + $this->db->query("SELECT position FROM __products WHERE id=? LIMIT 1", $id); + $position = $this->db->result('position'); + + $this->db->query("SELECT pc.category_id FROM __products_categories pc WHERE product_id=? ORDER BY position LIMIT 1", $id); + $category_id = $this->db->result('category_id'); + + $query = $this->db->placehold("SELECT id FROM __products p, __products_categories pc WHERE pc.product_id=p.id AND p.position>? AND pc.position=(SELECT MIN(pc2.position) FROM __products_categories pc2 WHERE pc.product_id=pc2.product_id) AND pc.category_id=? AND p.visible ORDER BY p.position limit 1", $position, $category_id); - $this->db->query($query); + $this->db->query($query); - return $this->get_product((integer)$this->db->result('id')); - } + return $this->get_product((integer)$this->db->result('id')); + } - /* - * - * Предыдущий товар - * - */ - public function get_prev_product($id) - { - $this->db->query("SELECT position FROM __products WHERE id=? LIMIT 1", $id); - $position = $this->db->result('position'); + /* + * + * Предыдущий товар + * + */ + public function get_prev_product($id) + { + $this->db->query("SELECT position FROM __products WHERE id=? LIMIT 1", $id); + $position = $this->db->result('position'); - $this->db->query("SELECT pc.category_id FROM __products_categories pc WHERE product_id=? ORDER BY position LIMIT 1", $id); - $category_id = $this->db->result('category_id'); + $this->db->query("SELECT pc.category_id FROM __products_categories pc WHERE product_id=? ORDER BY position LIMIT 1", $id); + $category_id = $this->db->result('category_id'); - $query = $this->db->placehold("SELECT id FROM __products p, __products_categories pc + $query = $this->db->placehold("SELECT id FROM __products p, __products_categories pc WHERE pc.product_id=p.id AND p.positiondb->query($query); - - return $this->get_product((integer)$this->db->result('id')); - } - + $this->db->query($query); + return $this->get_product((integer)$this->db->result('id')); + } } diff --git a/api/Request.php b/api/Request.php index ef98bcd..3ccb744 100755 --- a/api/Request.php +++ b/api/Request.php @@ -15,306 +15,312 @@ class Request extends Simpla { - /** - * Конструктор, чистка слешей - */ - public function __construct() - { - parent::__construct(); - - if(get_magic_quotes_gpc()) - { - $_POST = $this->stripslashes_recursive($_POST); - $_GET = $this->stripslashes_recursive($_GET); - $_COOKIE = $this->stripslashes_recursive($_COOKIE); - $_REQUEST = $this->stripslashes_recursive($_REQUEST); - } - - } - - /** - * Определение request-метода обращения к странице (GET, POST) - * Если задан аргумент функции (название метода, в любом регистре), возвращает true или false - * Если аргумент не задан, возвращает имя метода - * Пример: - * - * if($simpla->request->method('post')) - * print 'Request method is POST'; - * - */ - public function method($method = null) - { - if(!empty($method)) - return strtolower($_SERVER['REQUEST_METHOD']) == strtolower($method); - return $_SERVER['REQUEST_METHOD']; - } - - /** - * Возвращает переменную _GET, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра - * Второй параметр $type может иметь такие значения: integer, string, boolean - * Если $type не задан, возвращает переменную в чистом виде - */ - public function get($name, $type = null) - { - $val = null; - if(isset($_GET[$name])) - $val = $_GET[$name]; - - if(!empty($type) && is_array($val)) - $val = reset($val); - - if($type == 'string') - return strval(preg_replace('/[^\p{L}\p{Nd}\d\s_\-\.\%\s]/ui', '', $val)); - - if($type == 'integer') - return intval($val); - - if($type == 'boolean') - return !empty($val); - - return $val; - } - - /** - * Возвращает переменную _POST, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра - * Второй параметр $type может иметь такие значения: integer, string, boolean - * Если $type не задан, возвращает переменную в чистом виде - */ - public function post($name = null, $type = null) - { - $val = null; - if(!empty($name) && isset($_POST[$name])) - $val = $_POST[$name]; - elseif(empty($name)) - $val = file_get_contents('php://input'); - - if($type == 'string') - return strval(preg_replace('/[^\p{L}\p{Nd}\d\s_\-\.\%\s]/ui', '', $val)); - - if($type == 'integer') - return intval($val); - - if($type == 'boolean') - return !empty($val); - - return $val; - } - - /** - * Возвращает переменную _FILES - * Обычно переменные _FILES являются двухмерными массивами, поэтому можно указать второй параметр, - * например, чтобы получить имя загруженного файла: $filename = $simpla->request->files('myfile', 'name'); - */ - public function files($name, $name2 = null) - { - if(!empty($name2) && !empty($_FILES[$name][$name2])) - return $_FILES[$name][$name2]; - elseif(empty($name2) && !empty($_FILES[$name])) - return $_FILES[$name]; - else - return null; - } - - /** - * Рекурсивная чистка магических слешей - */ - - private function stripslashes_recursive($var) - { - if (is_array($var)) - { - $res = array(); - foreach($var as $k => $v) - $res[$this->stripslashes_recursive($k)] = $this->stripslashes_recursive($v); - - return $res; - } - else - { - return stripslashes($var); - } - } - - - /** - * Проверка сессии - */ - public function check_session() - { - if(!empty($_POST)) - { - if(empty($_POST['session_id']) || $_POST['session_id'] != session_id()) - { - unset($_POST); - return false; - } - } - return true; - } - - - /** - * URL - */ - public function url($params = array()) - { - $url = @parse_url($_SERVER["REQUEST_URI"]); - parse_str($url['query'], $query); - - if(get_magic_quotes_gpc()) - foreach($query as &$v) - { - if(!is_array($v)) - $v = stripslashes(urldecode($v)); - } - - foreach($params as $name=>$value) - $query[$name] = $value; - - $query_is_empty = true; - foreach($query as $name=>$value) - if($value!=='' && $value!==null) - $query_is_empty = false; - - if(!$query_is_empty) - $url['query'] = http_build_query($query); - else - $url['query'] = null; - - $result = http_build_url(null, $url); - return $result; - } + /** + * Конструктор, чистка слешей + */ + public function __construct() + { + parent::__construct(); + + if (get_magic_quotes_gpc()) { + $_POST = $this->stripslashes_recursive($_POST); + $_GET = $this->stripslashes_recursive($_GET); + $_COOKIE = $this->stripslashes_recursive($_COOKIE); + $_REQUEST = $this->stripslashes_recursive($_REQUEST); + } + } + + /** + * Определение request-метода обращения к странице (GET, POST) + * Если задан аргумент функции (название метода, в любом регистре), возвращает true или false + * Если аргумент не задан, возвращает имя метода + * Пример: + * + * if($simpla->request->method('post')) + * print 'Request method is POST'; + * + */ + public function method($method = null) + { + if (!empty($method)) { + return strtolower($_SERVER['REQUEST_METHOD']) == strtolower($method); + } + return $_SERVER['REQUEST_METHOD']; + } + + /** + * Возвращает переменную _GET, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра + * Второй параметр $type может иметь такие значения: integer, string, boolean + * Если $type не задан, возвращает переменную в чистом виде + */ + public function get($name, $type = null) + { + $val = null; + if (isset($_GET[$name])) { + $val = $_GET[$name]; + } + + if (!empty($type) && is_array($val)) { + $val = reset($val); + } + + if ($type == 'string') { + return strval(preg_replace('/[^\p{L}\p{Nd}\d\s_\-\.\%\s]/ui', '', $val)); + } + + if ($type == 'integer') { + return intval($val); + } + + if ($type == 'boolean') { + return !empty($val); + } + + return $val; + } + + /** + * Возвращает переменную _POST, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра + * Второй параметр $type может иметь такие значения: integer, string, boolean + * Если $type не задан, возвращает переменную в чистом виде + */ + public function post($name = null, $type = null) + { + $val = null; + if (!empty($name) && isset($_POST[$name])) { + $val = $_POST[$name]; + } elseif (empty($name)) { + $val = file_get_contents('php://input'); + } + + if ($type == 'string') { + return strval(preg_replace('/[^\p{L}\p{Nd}\d\s_\-\.\%\s]/ui', '', $val)); + } + + if ($type == 'integer') { + return intval($val); + } + + if ($type == 'boolean') { + return !empty($val); + } + + return $val; + } + + /** + * Возвращает переменную _FILES + * Обычно переменные _FILES являются двухмерными массивами, поэтому можно указать второй параметр, + * например, чтобы получить имя загруженного файла: $filename = $simpla->request->files('myfile', 'name'); + */ + public function files($name, $name2 = null) + { + if (!empty($name2) && !empty($_FILES[$name][$name2])) { + return $_FILES[$name][$name2]; + } elseif (empty($name2) && !empty($_FILES[$name])) { + return $_FILES[$name]; + } else { + return null; + } + } + + /** + * Рекурсивная чистка магических слешей + */ + + private function stripslashes_recursive($var) + { + if (is_array($var)) { + $res = array(); + foreach ($var as $k => $v) { + $res[$this->stripslashes_recursive($k)] = $this->stripslashes_recursive($v); + } + + return $res; + } else { + return stripslashes($var); + } + } + + + /** + * Проверка сессии + */ + public function check_session() + { + if (!empty($_POST)) { + if (empty($_POST['session_id']) || $_POST['session_id'] != session_id()) { + unset($_POST); + return false; + } + } + return true; + } + + + /** + * URL + */ + public function url($params = array()) + { + $url = @parse_url($_SERVER["REQUEST_URI"]); + parse_str($url['query'], $query); + + if (get_magic_quotes_gpc()) { + foreach ($query as &$v) { + if (!is_array($v)) { + $v = stripslashes(urldecode($v)); + } + } + } + + foreach ($params as $name=>$value) { + $query[$name] = $value; + } + + $query_is_empty = true; + foreach ($query as $name=>$value) { + if ($value!=='' && $value!==null) { + $query_is_empty = false; + } + } + + if (!$query_is_empty) { + $url['query'] = http_build_query($query); + } else { + $url['query'] = null; + } + + $result = http_build_url(null, $url); + return $result; + } } -if (!function_exists('http_build_url')) -{ - define('HTTP_URL_REPLACE', 1); // Replace every part of the first URL when there's one of the second URL - define('HTTP_URL_JOIN_PATH', 2); // Join relative paths - define('HTTP_URL_JOIN_QUERY', 4); // Join query strings - define('HTTP_URL_STRIP_USER', 8); // Strip any user authentication information - define('HTTP_URL_STRIP_PASS', 16); // Strip any password authentication information - define('HTTP_URL_STRIP_AUTH', 32); // Strip any authentication information - define('HTTP_URL_STRIP_PORT', 64); // Strip explicit port numbers - define('HTTP_URL_STRIP_PATH', 128); // Strip complete path - define('HTTP_URL_STRIP_QUERY', 256); // Strip query string - define('HTTP_URL_STRIP_FRAGMENT', 512); // Strip any fragments (#identifier) - define('HTTP_URL_STRIP_ALL', 1024); // Strip anything but scheme and host - - // Build an URL - // The parts of the second URL will be merged into the first according to the flags argument. - // - // @param mixed (Part(s) of) an URL in form of a string or associative array like parse_url() returns - // @param mixed Same as the first argument - // @param int A bitmask of binary or'ed HTTP_URL constants (Optional)HTTP_URL_REPLACE is the default - // @param array If set, it will be filled with the parts of the composed url like parse_url() would return - function http_build_url($url, $parts=array(), $flags=HTTP_URL_REPLACE, &$new_url=false) - { - $keys = array('user','pass','port','path','query','fragment'); - - // HTTP_URL_STRIP_ALL becomes all the HTTP_URL_STRIP_Xs - if ($flags & HTTP_URL_STRIP_ALL) - { - $flags |= HTTP_URL_STRIP_USER; - $flags |= HTTP_URL_STRIP_PASS; - $flags |= HTTP_URL_STRIP_PORT; - $flags |= HTTP_URL_STRIP_PATH; - $flags |= HTTP_URL_STRIP_QUERY; - $flags |= HTTP_URL_STRIP_FRAGMENT; - } - // HTTP_URL_STRIP_AUTH becomes HTTP_URL_STRIP_USER and HTTP_URL_STRIP_PASS - else if ($flags & HTTP_URL_STRIP_AUTH) - { - $flags |= HTTP_URL_STRIP_USER; - $flags |= HTTP_URL_STRIP_PASS; - } - - // Parse the original URL - $parse_url = parse_url($url); - - // Scheme and Host are always replaced - if (isset($parts['scheme'])) - $parse_url['scheme'] = $parts['scheme']; - if (isset($parts['host'])) - $parse_url['host'] = $parts['host']; - - // (If applicable) Replace the original URL with it's new parts - if ($flags & HTTP_URL_REPLACE) - { - foreach ($keys as $key) - { - if (isset($parts[$key])) - $parse_url[$key] = $parts[$key]; - } - } - else - { - // Join the original URL path with the new path - if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH)) - { - if (isset($parse_url['path'])) - $parse_url['path'] = rtrim(str_replace(basename($parse_url['path']), '', $parse_url['path']), '/') . '/' . ltrim($parts['path'], '/'); - else - $parse_url['path'] = $parts['path']; - } - - // Join the original query string with the new query string - if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY)) - { - if (isset($parse_url['query'])) - $parse_url['query'] .= '&' . $parts['query']; - else - $parse_url['query'] = $parts['query']; - } - } - - // Strips all the applicable sections of the URL - // Note: Scheme and Host are never stripped - foreach ($keys as $key) - { - if ($flags & (int)constant('HTTP_URL_STRIP_' . strtoupper($key))) - unset($parse_url[$key]); - } - - - $new_url = $parse_url; - - return - ((isset($parse_url['scheme'])) ? $parse_url['scheme'] . '://' : '') - .((isset($parse_url['user'])) ? $parse_url['user'] . ((isset($parse_url['pass'])) ? ':' . $parse_url['pass'] : '') .'@' : '') - .((isset($parse_url['host'])) ? $parse_url['host'] : '') - .((isset($parse_url['port'])) ? ':' . $parse_url['port'] : '') - .((isset($parse_url['path'])) ? $parse_url['path'] : '') - .((isset($parse_url['query'])) ? '?' . $parse_url['query'] : '') - .((isset($parse_url['fragment'])) ? '#' . $parse_url['fragment'] : '') - ; - } +if (!function_exists('http_build_url')) { + define('HTTP_URL_REPLACE', 1); // Replace every part of the first URL when there's one of the second URL + define('HTTP_URL_JOIN_PATH', 2); // Join relative paths + define('HTTP_URL_JOIN_QUERY', 4); // Join query strings + define('HTTP_URL_STRIP_USER', 8); // Strip any user authentication information + define('HTTP_URL_STRIP_PASS', 16); // Strip any password authentication information + define('HTTP_URL_STRIP_AUTH', 32); // Strip any authentication information + define('HTTP_URL_STRIP_PORT', 64); // Strip explicit port numbers + define('HTTP_URL_STRIP_PATH', 128); // Strip complete path + define('HTTP_URL_STRIP_QUERY', 256); // Strip query string + define('HTTP_URL_STRIP_FRAGMENT', 512); // Strip any fragments (#identifier) + define('HTTP_URL_STRIP_ALL', 1024); // Strip anything but scheme and host + + // Build an URL + // The parts of the second URL will be merged into the first according to the flags argument. + // + // @param mixed (Part(s) of) an URL in form of a string or associative array like parse_url() returns + // @param mixed Same as the first argument + // @param int A bitmask of binary or'ed HTTP_URL constants (Optional)HTTP_URL_REPLACE is the default + // @param array If set, it will be filled with the parts of the composed url like parse_url() would return + function http_build_url($url, $parts=array(), $flags=HTTP_URL_REPLACE, &$new_url=false) + { + $keys = array('user','pass','port','path','query','fragment'); + + // HTTP_URL_STRIP_ALL becomes all the HTTP_URL_STRIP_Xs + if ($flags & HTTP_URL_STRIP_ALL) { + $flags |= HTTP_URL_STRIP_USER; + $flags |= HTTP_URL_STRIP_PASS; + $flags |= HTTP_URL_STRIP_PORT; + $flags |= HTTP_URL_STRIP_PATH; + $flags |= HTTP_URL_STRIP_QUERY; + $flags |= HTTP_URL_STRIP_FRAGMENT; + } + // HTTP_URL_STRIP_AUTH becomes HTTP_URL_STRIP_USER and HTTP_URL_STRIP_PASS + elseif ($flags & HTTP_URL_STRIP_AUTH) { + $flags |= HTTP_URL_STRIP_USER; + $flags |= HTTP_URL_STRIP_PASS; + } + + // Parse the original URL + $parse_url = parse_url($url); + + // Scheme and Host are always replaced + if (isset($parts['scheme'])) { + $parse_url['scheme'] = $parts['scheme']; + } + if (isset($parts['host'])) { + $parse_url['host'] = $parts['host']; + } + + // (If applicable) Replace the original URL with it's new parts + if ($flags & HTTP_URL_REPLACE) { + foreach ($keys as $key) { + if (isset($parts[$key])) { + $parse_url[$key] = $parts[$key]; + } + } + } else { + // Join the original URL path with the new path + if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH)) { + if (isset($parse_url['path'])) { + $parse_url['path'] = rtrim(str_replace(basename($parse_url['path']), '', $parse_url['path']), '/') . '/' . ltrim($parts['path'], '/'); + } else { + $parse_url['path'] = $parts['path']; + } + } + + // Join the original query string with the new query string + if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY)) { + if (isset($parse_url['query'])) { + $parse_url['query'] .= '&' . $parts['query']; + } else { + $parse_url['query'] = $parts['query']; + } + } + } + + // Strips all the applicable sections of the URL + // Note: Scheme and Host are never stripped + foreach ($keys as $key) { + if ($flags & (int)constant('HTTP_URL_STRIP_' . strtoupper($key))) { + unset($parse_url[$key]); + } + } + + + $new_url = $parse_url; + + return + ((isset($parse_url['scheme'])) ? $parse_url['scheme'] . '://' : '') + .((isset($parse_url['user'])) ? $parse_url['user'] . ((isset($parse_url['pass'])) ? ':' . $parse_url['pass'] : '') .'@' : '') + .((isset($parse_url['host'])) ? $parse_url['host'] : '') + .((isset($parse_url['port'])) ? ':' . $parse_url['port'] : '') + .((isset($parse_url['path'])) ? $parse_url['path'] : '') + .((isset($parse_url['query'])) ? '?' . $parse_url['query'] : '') + .((isset($parse_url['fragment'])) ? '#' . $parse_url['fragment'] : '') + ; + } } -if(!function_exists('http_build_query')) { - function http_build_query($data,$prefix=null,$sep='',$key='') { - $ret = array(); - foreach((array)$data as $k => $v) { - $k = urlencode($k); - if(is_int($k) && $prefix != null) { - $k = $prefix.$k; - }; - if(!empty($key)) { - $k = $key."[".$k."]"; - }; - - if(is_array($v) || is_object($v)) { - array_push($ret,http_build_query($v,"",$sep,$k)); - } - else { - array_push($ret,$k."=".urlencode($v)); - }; - }; - - if(empty($sep)) { - $sep = ini_get("arg_separator.output"); - }; - - return implode($sep, $ret); - }; +if (!function_exists('http_build_query')) { + function http_build_query($data, $prefix=null, $sep='', $key='') + { + $ret = array(); + foreach ((array)$data as $k => $v) { + $k = urlencode($k); + if (is_int($k) && $prefix != null) { + $k = $prefix.$k; + }; + if (!empty($key)) { + $k = $key."[".$k."]"; + }; + + if (is_array($v) || is_object($v)) { + array_push($ret, http_build_query($v, "", $sep, $k)); + } else { + array_push($ret, $k."=".urlencode($v)); + }; + }; + + if (empty($sep)) { + $sep = ini_get("arg_separator.output"); + }; + + return implode($sep, $ret); + }; }; diff --git a/api/Settings.php b/api/Settings.php index 3f6ebf6..9d47311 100755 --- a/api/Settings.php +++ b/api/Settings.php @@ -14,50 +14,56 @@ class Settings extends Simpla { - private $vars = array(); - - public function __construct() - { - parent::__construct(); - - // Выбираем из базы настройки - $this->db->query('SELECT name, value FROM __settings'); - - // и записываем их в переменную - foreach($this->db->results() as $result) - if(!($this->vars[$result->name] = @unserialize($result->value))) - $this->vars[$result->name] = $result->value; - } - - public function __get($name) - { - if($res = parent::__get($name)) - return $res; - - if(isset($this->vars[$name])) - return $this->vars[$name]; - else - return null; - } - - public function __set($name, $value) - { - $this->vars[$name] = $value; - - if(is_array($value)) - $value = serialize($value); - else - $value = (string) $value; - - $this->db->query('SELECT count(*) as count FROM __settings WHERE name=?', $name); - if($this->db->result('count')>0) - $this->db->query('UPDATE __settings SET value=? WHERE name=?', $value, $name); - else - $this->db->query('INSERT INTO __settings SET value=?, name=?', $value, $name); - } - - public function __isset($name) - { - return isset($this->vars[$name]); - } + private $vars = array(); + + public function __construct() + { + parent::__construct(); + + // Выбираем из базы настройки + $this->db->query('SELECT name, value FROM __settings'); + + // и записываем их в переменную + foreach ($this->db->results() as $result) { + if (!($this->vars[$result->name] = @unserialize($result->value))) { + $this->vars[$result->name] = $result->value; + } + } + } + + public function __get($name) + { + if ($res = parent::__get($name)) { + return $res; + } + + if (isset($this->vars[$name])) { + return $this->vars[$name]; + } else { + return null; + } + } + + public function __set($name, $value) + { + $this->vars[$name] = $value; + + if (is_array($value)) { + $value = serialize($value); + } else { + $value = (string) $value; + } + + $this->db->query('SELECT count(*) as count FROM __settings WHERE name=?', $name); + if ($this->db->result('count')>0) { + $this->db->query('UPDATE __settings SET value=? WHERE name=?', $value, $name); + } else { + $this->db->query('INSERT INTO __settings SET value=?, name=?', $value, $name); + } + } + + public function __isset($name) + { + return isset($this->vars[$name]); + } } diff --git a/api/Simpla.php b/api/Simpla.php index dbeff97..6efe85f 100755 --- a/api/Simpla.php +++ b/api/Simpla.php @@ -14,96 +14,88 @@ */ class Simpla { - // Свойства - Классы API - private $classes = array( - 'config' => 'Config', - 'request' => 'Request', - 'db' => 'Database', - 'settings' => 'Settings', - 'design' => 'Design', - 'products' => 'Products', - 'variants' => 'Variants', - 'categories' => 'Categories', - 'brands' => 'Brands', - 'features' => 'Features', - 'money' => 'Money', - 'pages' => 'Pages', - 'blog' => 'Blog', - 'cart' => 'Cart', - 'image' => 'Image', - 'delivery' => 'Delivery', - 'payment' => 'Payment', - 'orders' => 'Orders', - 'users' => 'Users', - 'coupons' => 'Coupons', - 'comments' => 'Comments', - 'feedbacks' => 'Feedbacks', - 'notify' => 'Notify', - 'managers' => 'Managers' - ); + // Свойства - Классы API + private $classes = array( + 'config' => 'Config', + 'request' => 'Request', + 'db' => 'Database', + 'settings' => 'Settings', + 'design' => 'Design', + 'products' => 'Products', + 'variants' => 'Variants', + 'categories' => 'Categories', + 'brands' => 'Brands', + 'features' => 'Features', + 'money' => 'Money', + 'pages' => 'Pages', + 'blog' => 'Blog', + 'cart' => 'Cart', + 'image' => 'Image', + 'delivery' => 'Delivery', + 'payment' => 'Payment', + 'orders' => 'Orders', + 'users' => 'Users', + 'coupons' => 'Coupons', + 'comments' => 'Comments', + 'feedbacks' => 'Feedbacks', + 'notify' => 'Notify', + 'managers' => 'Managers' + ); - // Созданные объекты - private static $objects = array(); + // Созданные объекты + private static $objects = array(); - /** - * Конструктор оставим пустым, но определим его на случай обращения parent::__construct() в классах API - */ - public function __construct() - { - //error_reporting(E_ALL & !E_STRICT); - } + /** + * Конструктор оставим пустым, но определим его на случай обращения parent::__construct() в классах API + */ + public function __construct() + { + //error_reporting(E_ALL & !E_STRICT); + } - /** - * Магический метод, создает нужный объект API - */ - public function __get($name) - { - // Если такой объект уже существует, возвращаем его - if(isset(self::$objects[$name])) - { - return(self::$objects[$name]); - } + /** + * Магический метод, создает нужный объект API + */ + public function __get($name) + { + // Если такой объект уже существует, возвращаем его + if (isset(self::$objects[$name])) { + return(self::$objects[$name]); + } - // Если запрошенного API не существует - ошибка - if(!array_key_exists($name, $this->classes)) - { - return null; - } + // Если запрошенного API не существует - ошибка + if (!array_key_exists($name, $this->classes)) { + return null; + } - // Определяем имя нужного класса - $class = $this->classes[$name]; + // Определяем имя нужного класса + $class = $this->classes[$name]; - // Подключаем его - include_once(dirname(__FILE__).'/'.$class.'.php'); + // Подключаем его + include_once(dirname(__FILE__).'/'.$class.'.php'); - // Сохраняем для будущих обращений к нему - self::$objects[$name] = new $class(); + // Сохраняем для будущих обращений к нему + self::$objects[$name] = new $class(); - // Возвращаем созданный объект - return self::$objects[$name]; - } + // Возвращаем созданный объект + return self::$objects[$name]; + } - /* - Вспомогательные методы - */ + /* + Вспомогательные методы + */ - public function convert_str_encoding($str, $to_encoding, $from_encoding, $alt = false) - { + public function convert_str_encoding($str, $to_encoding, $from_encoding, $alt = false) + { + if (function_exists('iconv')) { + $str = @iconv($from_encoding, $to_encoding, $str); + } elseif (function_exists('mb_convert_encoding')) { + $str = @mb_convert_encoding($str, $to_encoding, $from_encoding); + } else { + // TODO add сonverting Windows-1251 to UTF-8 and the reverse when no iconv and mb_convert_encoding + return $alt ? $alt : $str; + } - if (function_exists('iconv')) - { - $str = @iconv($from_encoding, $to_encoding, $str); - } - elseif (function_exists('mb_convert_encoding')) - { - $str = @mb_convert_encoding($str, $to_encoding, $from_encoding); - } - else - { - // TODO add сonverting Windows-1251 to UTF-8 and the reverse when no iconv and mb_convert_encoding - return $alt ? $alt : $str; - } - - return $str; - } + return $str; + } } diff --git a/api/Users.php b/api/Users.php index 7b59f1d..825c567 100755 --- a/api/Users.php +++ b/api/Users.php @@ -13,210 +13,219 @@ class Users extends Simpla { - // осторожно, при изменении соли испортятся текущие пароли пользователей - private $salt = '8e86a279d6e182b3c811c559e6b15484'; - - public function get_users($filter = array()) - { - $limit = 1000; - $page = 1; - $group_id_filter = ''; - $keyword_filter = ''; - - if(isset($filter['limit'])) - $limit = max(1, intval($filter['limit'])); - - if(isset($filter['page'])) - $page = max(1, intval($filter['page'])); - - if(isset($filter['group_id'])) - $group_id_filter = $this->db->placehold('AND u.group_id in(?@)', (array)$filter['group_id']); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (u.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.email LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.last_ip LIKE "%'.$this->db->escape(trim($keyword)).'%")'); - } - - $order = 'u.name'; - if(!empty($filter['sort'])) - switch ($filter['sort']) - { - case 'date': - $order = 'u.created DESC'; - break; - - case 'name': - $order = 'u.name'; - break; - } - - - $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); - // Выбираем пользователей - $query = $this->db->placehold("SELECT u.id, u.email, u.password, u.name, u.group_id, u.enabled, u.last_ip, u.created, g.discount, g.name as group_name + // осторожно, при изменении соли испортятся текущие пароли пользователей + private $salt = '8e86a279d6e182b3c811c559e6b15484'; + + public function get_users($filter = array()) + { + $limit = 1000; + $page = 1; + $group_id_filter = ''; + $keyword_filter = ''; + + if (isset($filter['limit'])) { + $limit = max(1, intval($filter['limit'])); + } + + if (isset($filter['page'])) { + $page = max(1, intval($filter['page'])); + } + + if (isset($filter['group_id'])) { + $group_id_filter = $this->db->placehold('AND u.group_id in(?@)', (array)$filter['group_id']); + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (u.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.email LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.last_ip LIKE "%'.$this->db->escape(trim($keyword)).'%")'); + } + } + + $order = 'u.name'; + if (!empty($filter['sort'])) { + switch ($filter['sort']) { + case 'date': + $order = 'u.created DESC'; + break; + + case 'name': + $order = 'u.name'; + break; + } + } + + + $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit); + // Выбираем пользователей + $query = $this->db->placehold("SELECT u.id, u.email, u.password, u.name, u.group_id, u.enabled, u.last_ip, u.created, g.discount, g.name as group_name FROM __users u LEFT JOIN __groups g ON u.group_id=g.id WHERE 1 $group_id_filter $keyword_filter ORDER BY $order $sql_limit"); - $this->db->query($query); - return $this->db->results(); - } - - public function count_users($filter = array()) - { - $group_id_filter = ''; - $keyword_filter = ''; - - if(isset($filter['group_id'])) - $group_id_filter = $this->db->placehold('AND u.group_id in(?@)', (array)$filter['group_id']); - - if(isset($filter['keyword'])) - { - $keywords = explode(' ', $filter['keyword']); - foreach($keywords as $keyword) - $keyword_filter .= $this->db->placehold('AND (u.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.email LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.last_ip LIKE "%'.$this->db->escape(trim($keyword)).'%")'); - } - - // Выбираем пользователей - $query = $this->db->placehold("SELECT count(*) as count + $this->db->query($query); + return $this->db->results(); + } + + public function count_users($filter = array()) + { + $group_id_filter = ''; + $keyword_filter = ''; + + if (isset($filter['group_id'])) { + $group_id_filter = $this->db->placehold('AND u.group_id in(?@)', (array)$filter['group_id']); + } + + if (isset($filter['keyword'])) { + $keywords = explode(' ', $filter['keyword']); + foreach ($keywords as $keyword) { + $keyword_filter .= $this->db->placehold('AND (u.name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.email LIKE "%'.$this->db->escape(trim($keyword)).'%" OR u.last_ip LIKE "%'.$this->db->escape(trim($keyword)).'%")'); + } + } + + // Выбираем пользователей + $query = $this->db->placehold("SELECT count(*) as count FROM __users u LEFT JOIN __groups g ON u.group_id=g.id WHERE 1 $group_id_filter $keyword_filter"); - $this->db->query($query); - return $this->db->result('count'); - } - - public function get_user($id) - { - if(gettype($id) == 'string') - $where = $this->db->placehold(' WHERE u.email=? ', $id); - else - $where = $this->db->placehold(' WHERE u.id=? ', intval($id)); - - // Выбираем пользователя - $query = $this->db->placehold("SELECT u.id, u.email, u.password, u.name, u.group_id, u.enabled, u.last_ip, u.created, g.discount, g.name as group_name + $this->db->query($query); + return $this->db->result('count'); + } + + public function get_user($id) + { + if (gettype($id) == 'string') { + $where = $this->db->placehold(' WHERE u.email=? ', $id); + } else { + $where = $this->db->placehold(' WHERE u.id=? ', intval($id)); + } + + // Выбираем пользователя + $query = $this->db->placehold("SELECT u.id, u.email, u.password, u.name, u.group_id, u.enabled, u.last_ip, u.created, g.discount, g.name as group_name FROM __users u LEFT JOIN __groups g ON u.group_id=g.id $where LIMIT 1", $id); - $this->db->query($query); - $user = $this->db->result(); - if(empty($user)) - return false; - $user->discount *= 1; // Убираем лишние нули, чтобы было 5 вместо 5.00 - return $user; - } - - public function add_user($user) - { - $user = (array)$user; - if(isset($user['password'])) - $user['password'] = md5($this->salt.$user['password'].md5($user['password'])); - - $query = $this->db->placehold("SELECT count(*) as count + $this->db->query($query); + $user = $this->db->result(); + if (empty($user)) { + return false; + } + $user->discount *= 1; // Убираем лишние нули, чтобы было 5 вместо 5.00 + return $user; + } + + public function add_user($user) + { + $user = (array)$user; + if (isset($user['password'])) { + $user['password'] = md5($this->salt.$user['password'].md5($user['password'])); + } + + $query = $this->db->placehold("SELECT count(*) as count FROM __users WHERE email=?", $user['email']); - $this->db->query($query); - - if($this->db->result('count') > 0) - return false; - - $query = $this->db->placehold("INSERT INTO __users SET ?%", $user); - $this->db->query($query); - return $this->db->insert_id(); - } - - public function update_user($id, $user) - { - $user = (array)$user; - if(isset($user['password'])) - $user['password'] = md5($this->salt.$user['password'].md5($user['password'])); - $query = $this->db->placehold("UPDATE __users SET ?% WHERE id=? LIMIT 1", $user, intval($id)); - $this->db->query($query); - return $id; - } - - public function delete_user($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("UPDATE __orders SET user_id=NULL WHERE user_id=?", intval($id)); - $this->db->query($query); - - $query = $this->db->placehold("DELETE FROM __users WHERE id=? LIMIT 1", intval($id)); - if($this->db->query($query)) - return true; - } - return false; - } - - public function get_groups() - { - // Выбираем группы - $query = $this->db->placehold("SELECT g.id, g.name, g.discount + $this->db->query($query); + + if ($this->db->result('count') > 0) { + return false; + } + + $query = $this->db->placehold("INSERT INTO __users SET ?%", $user); + $this->db->query($query); + return $this->db->insert_id(); + } + + public function update_user($id, $user) + { + $user = (array)$user; + if (isset($user['password'])) { + $user['password'] = md5($this->salt.$user['password'].md5($user['password'])); + } + $query = $this->db->placehold("UPDATE __users SET ?% WHERE id=? LIMIT 1", $user, intval($id)); + $this->db->query($query); + return $id; + } + + public function delete_user($id) + { + if (!empty($id)) { + $query = $this->db->placehold("UPDATE __orders SET user_id=NULL WHERE user_id=?", intval($id)); + $this->db->query($query); + + $query = $this->db->placehold("DELETE FROM __users WHERE id=? LIMIT 1", intval($id)); + if ($this->db->query($query)) { + return true; + } + } + return false; + } + + public function get_groups() + { + // Выбираем группы + $query = $this->db->placehold("SELECT g.id, g.name, g.discount FROM __groups AS g ORDER BY g.discount"); - $this->db->query($query); - return $this->db->results(); - } - - public function get_group($id) - { - // Выбираем группу - $query = $this->db->placehold("SELECT g.* + $this->db->query($query); + return $this->db->results(); + } + + public function get_group($id) + { + // Выбираем группу + $query = $this->db->placehold("SELECT g.* FROM __groups AS g WHERE g.id=? LIMIT 1", $id); - $this->db->query($query); - $group = $this->db->result(); - - return $group; - } - - - public function add_group($group) - { - $query = $this->db->placehold("INSERT INTO __groups SET ?%", $group); - $this->db->query($query); - return $this->db->insert_id(); - } - - public function update_group($id, $group) - { - $query = $this->db->placehold("UPDATE __groups SET ?% WHERE id=? LIMIT 1", $group, intval($id)); - $this->db->query($query); - return $id; - } - - public function delete_group($id) - { - if(!empty($id)) - { - $query = $this->db->placehold("UPDATE __users SET group_id=NULL WHERE group_id=? LIMIT 1", intval($id)); - $this->db->query($query); - - $query = $this->db->placehold("DELETE FROM __groups WHERE id=? LIMIT 1", intval($id)); - if($this->db->query($query)) - return true; - } - return false; - } - - public function check_password($email, $password) - { - $encpassword = md5($this->salt.$password.md5($password)); - $query = $this->db->placehold("SELECT id FROM __users WHERE email=? AND password=? LIMIT 1", $email, $encpassword); - $this->db->query($query); - if($id = $this->db->result('id')) - return $id; - - return false; - } - + $this->db->query($query); + $group = $this->db->result(); + + return $group; + } + + + public function add_group($group) + { + $query = $this->db->placehold("INSERT INTO __groups SET ?%", $group); + $this->db->query($query); + return $this->db->insert_id(); + } + + public function update_group($id, $group) + { + $query = $this->db->placehold("UPDATE __groups SET ?% WHERE id=? LIMIT 1", $group, intval($id)); + $this->db->query($query); + return $id; + } + + public function delete_group($id) + { + if (!empty($id)) { + $query = $this->db->placehold("UPDATE __users SET group_id=NULL WHERE group_id=? LIMIT 1", intval($id)); + $this->db->query($query); + + $query = $this->db->placehold("DELETE FROM __groups WHERE id=? LIMIT 1", intval($id)); + if ($this->db->query($query)) { + return true; + } + } + return false; + } + + public function check_password($email, $password) + { + $encpassword = md5($this->salt.$password.md5($password)); + $query = $this->db->placehold("SELECT id FROM __users WHERE email=? AND password=? LIMIT 1", $email, $encpassword); + $this->db->query($query); + if ($id = $this->db->result('id')) { + return $id; + } + + return false; + } } diff --git a/api/Variants.php b/api/Variants.php index 2a19130..19a5c87 100755 --- a/api/Variants.php +++ b/api/Variants.php @@ -14,30 +14,34 @@ class Variants extends Simpla { - /** - * Функция возвращает варианты товара - * @param $filter - * @retval array - */ - public function get_variants($filter = array()) - { - $product_id_filter = ''; - $variant_id_filter = ''; - $instock_filter = ''; - - if(!empty($filter['product_id'])) - $product_id_filter = $this->db->placehold('AND v.product_id in(?@)', (array)$filter['product_id']); - - if(!empty($filter['id'])) - $variant_id_filter = $this->db->placehold('AND v.id in(?@)', (array)$filter['id']); - - if(!empty($filter['in_stock']) && $filter['in_stock']) - $instock_filter = $this->db->placehold('AND (v.stock>0 OR v.stock IS NULL)'); - - if(!$product_id_filter && !$variant_id_filter) - return array(); - - $query = $this->db->placehold("SELECT v.id, v.product_id , v.price, NULLIF(v.compare_price, 0) as compare_price, v.sku, IFNULL(v.stock, ?) as stock, (v.stock IS NULL) as infinity, v.name, v.attachment, v.position + /** + * Функция возвращает варианты товара + * @param $filter + * @retval array + */ + public function get_variants($filter = array()) + { + $product_id_filter = ''; + $variant_id_filter = ''; + $instock_filter = ''; + + if (!empty($filter['product_id'])) { + $product_id_filter = $this->db->placehold('AND v.product_id in(?@)', (array)$filter['product_id']); + } + + if (!empty($filter['id'])) { + $variant_id_filter = $this->db->placehold('AND v.id in(?@)', (array)$filter['id']); + } + + if (!empty($filter['in_stock']) && $filter['in_stock']) { + $instock_filter = $this->db->placehold('AND (v.stock>0 OR v.stock IS NULL)'); + } + + if (!$product_id_filter && !$variant_id_filter) { + return array(); + } + + $query = $this->db->placehold("SELECT v.id, v.product_id , v.price, NULLIF(v.compare_price, 0) as compare_price, v.sku, IFNULL(v.stock, ?) as stock, (v.stock IS NULL) as infinity, v.name, v.attachment, v.position FROM __variants AS v WHERE 1 @@ -47,61 +51,61 @@ public function get_variants($filter = array()) ORDER BY v.position ", $this->settings->max_order_amount); - $this->db->query($query); - return $this->db->results(); - } + $this->db->query($query); + return $this->db->results(); + } - public function get_variant($id) - { - if(empty($id)) - return false; + public function get_variant($id) + { + if (empty($id)) { + return false; + } - $query = $this->db->placehold("SELECT v.id, v.product_id , v.price, NULLIF(v.compare_price, 0) as compare_price, v.sku, IFNULL(v.stock, ?) as stock, (v.stock IS NULL) as infinity, v.name, v.attachment + $query = $this->db->placehold("SELECT v.id, v.product_id , v.price, NULLIF(v.compare_price, 0) as compare_price, v.sku, IFNULL(v.stock, ?) as stock, (v.stock IS NULL) as infinity, v.name, v.attachment FROM __variants v WHERE v.id=? LIMIT 1", $this->settings->max_order_amount, $id); - $this->db->query($query); - $variant = $this->db->result(); - return $variant; - } - - public function update_variant($id, $variant) - { - $query = $this->db->placehold("UPDATE __variants SET ?% WHERE id=? LIMIT 1", $variant, intval($id)); - $this->db->query($query); - return $id; - } - - public function add_variant($variant) - { - $query = $this->db->placehold("INSERT INTO __variants SET ?%", $variant); - $this->db->query($query); - return $this->db->insert_id(); - } - - public function delete_variant($id) - { - if(!empty($id)) - { - $this->delete_attachment($id); - $query = $this->db->placehold("DELETE FROM __variants WHERE id = ? LIMIT 1", intval($id)); - $this->db->query($query); - $this->db->query('UPDATE __purchases SET variant_id=NULL WHERE variant_id=?', intval($id)); - } - } - - public function delete_attachment($id) - { - $query = $this->db->placehold("SELECT attachment FROM __variants WHERE id=?", $id); - $this->db->query($query); - $filename = $this->db->result('attachment'); - $query = $this->db->placehold("SELECT 1 FROM __variants WHERE attachment=? AND id!=?", $filename, $id); - $this->db->query($query); - $exists = $this->db->num_rows(); - if(!empty($filename) && $exists == 0) - @unlink($this->config->root_dir.'/'.$this->config->downloads_dir.$filename); - $this->update_variant($id, array('attachment'=>null)); - } - + $this->db->query($query); + $variant = $this->db->result(); + return $variant; + } + + public function update_variant($id, $variant) + { + $query = $this->db->placehold("UPDATE __variants SET ?% WHERE id=? LIMIT 1", $variant, intval($id)); + $this->db->query($query); + return $id; + } + + public function add_variant($variant) + { + $query = $this->db->placehold("INSERT INTO __variants SET ?%", $variant); + $this->db->query($query); + return $this->db->insert_id(); + } + + public function delete_variant($id) + { + if (!empty($id)) { + $this->delete_attachment($id); + $query = $this->db->placehold("DELETE FROM __variants WHERE id = ? LIMIT 1", intval($id)); + $this->db->query($query); + $this->db->query('UPDATE __purchases SET variant_id=NULL WHERE variant_id=?', intval($id)); + } + } + + public function delete_attachment($id) + { + $query = $this->db->placehold("SELECT attachment FROM __variants WHERE id=?", $id); + $this->db->query($query); + $filename = $this->db->result('attachment'); + $query = $this->db->placehold("SELECT 1 FROM __variants WHERE attachment=? AND id!=?", $filename, $id); + $this->db->query($query); + $exists = $this->db->num_rows(); + if (!empty($filename) && $exists == 0) { + @unlink($this->config->root_dir.'/'.$this->config->downloads_dir.$filename); + } + $this->update_variant($id, array('attachment'=>null)); + } }