diff --git a/autoload/.DS_Store b/autoload/.DS_Store deleted file mode 100644 index 3239922..0000000 Binary files a/autoload/.DS_Store and /dev/null differ diff --git a/autoload/admin/factory/class.ShopProduct.php b/autoload/admin/factory/class.ShopProduct.php index 90d5e09..c2e8c4a 100644 --- a/autoload/admin/factory/class.ShopProduct.php +++ b/autoload/admin/factory/class.ShopProduct.php @@ -622,53 +622,6 @@ class ShopProduct return $result; } - public static function permutation_quantity($id_product, $permutation) - { - global $mdb; - - return $mdb -> get('pp_shop_products_stock', 'quantity', ['AND' => ['id_product' => $id_product, 'permutation' => $permutation]]); - } - - public static function stock_save($id_product, $permutations_quantity) - { - global $mdb; - - $mdb -> delete( 'pp_shop_products_stock', [ 'id_product' => $id_product ] ); - - if ( is_array( $permutations_quantity ) ) foreach ($permutations_quantity as $key => $val) - { - $permutations[] = $mdb -> get('pp_shop_products_stock', 'id', ['AND' => ['id_product' => $id_product, 'permutation' => $key]]); - $mdb -> delete('pp_shop_products_stock', ['AND' => ['id_product' => $id_product, 'id[!]' => $permutations]]); - } - - if (\is_array($permutations_quantity)) - { - foreach ($permutations_quantity as $key => $val) - { - if ($id = $mdb -> get('pp_shop_products_stock', 'id', ['AND' => ['id_product' => $id_product, 'permutation' => $key]])) - { - $mdb -> update('pp_shop_products_stock', [ - 'quantity' => $val, - ], [ - 'id' => $id, - ]); - \S::delete_dir('../temp/'); - } - else - { - $mdb -> insert('pp_shop_products_stock', [ - 'id_product' => $id_product, - 'permutation' => $key, - 'quantity' => $val, - ]); - \S::delete_dir('../temp/'); - } - } - } - - return true; - } - // product_unarchive static public function product_unarchive( int $product_id ) { @@ -1050,12 +1003,6 @@ class ShopProduct \admin\factory\ShopProduct::update_product_combinations_prices( $product_id, $price_brutto, $vat, $price_brutto_promo ); - //stan magazynowy - if ( $mdb -> count( 'pp_shop_products_stock', [ 'id_product' => $product_id ] ) ) - $mdb -> update( 'pp_shop_products_stock', [ 'quantity' => $quantity ], [ 'id_product' => $product_id ] ); - else - $mdb -> insert( 'pp_shop_products_stock', [ 'id_product' => $product_id, 'quantity' => $quantity ] ); - foreach ( $name as $key => $val ) { if ( $translation_id = $mdb -> get( 'pp_shop_products_langs', 'id', [ 'AND' => [ 'product_id' => $product_id, 'lang_id' => $key ] ] ) ) diff --git a/autoload/class.Article.php b/autoload/class.Article.php index 170c848..3998a06 100644 --- a/autoload/class.Article.php +++ b/autoload/class.Article.php @@ -39,8 +39,6 @@ class Article implements \ArrayAccess $this -> images = $mdb -> select( 'pp_articles_images', '*', [ 'article_id' => (int)$article_id, 'ORDER' => [ 'o' => 'ASC', 'id' => 'ASC' ] ] ); $this -> files = $mdb -> select( 'pp_articles_files', '*', [ 'article_id' => (int)$article_id ] ); $this -> pages = $mdb -> select( 'pp_articles_pages', 'page_id', [ 'article_id' => (int)$article_id ] ); - $this -> tags = $mdb -> select( 'pp_tags', [ '[><]pp_articles_tags' => [ 'id' => 'tag_id' ] ], 'name', [ 'article_id' => (int)$article_id ] ); - $results = $mdb -> select( 'pp_articles_additional_params', [ '[><]pp_articles_additional_values' => [ 'id' => 'param_id' ] ], [ 'name', 'value', 'language_id' ], [ 'article_id' => (int)$article_id ] ); if ( is_array( $results ) ) foreach ( $results as $row ) { if ( !$row['language_id'] ) @@ -51,7 +49,7 @@ class Article implements \ArrayAccess $this -> params = $params; } - public function get_from_cache( $article_id, $lang_id ) + static public function get_from_cache( $article_id, $lang_id ) { $cacheHandler = new \CacheHandler(); $cacheKey = "\Article::get_from_cache:$article_id:$lang_id"; diff --git a/autoload/class.Image.php b/autoload/class.Image.php index d767133..0065afa 100644 --- a/autoload/class.Image.php +++ b/autoload/class.Image.php @@ -1,64 +1,82 @@ file = $file; + if ($file !== null) { + $this->file = $file; - if ( is_file( $file ) ) - $this->setImageFile($file); - else - $this->setImageString($file); - } + if (is_file($file)) { + $this->setImageFile($file); + } else { + $this->setImageString($file); + } + } } /** * Set image resource from file * * @param string $file Path to image file - * @return ImageManipulator for a fluent interface + * @return self * @throws InvalidArgumentException */ - public function setImageFile($file) + public function setImageFile(string $file): self { if (!(is_readable($file) && is_file($file))) { throw new InvalidArgumentException("Image file $file is not readable"); } - if (is_resource($this->image)) { + if (isset($this->image) && $this->image instanceof \GdImage) { imagedestroy($this->image); } - list ( $this -> width, $this -> height, $type ) = getimagesize($file); + [$width, $height, $type] = getimagesize($file); + + if ($width === false || $height === false) { + throw new InvalidArgumentException("Unable to get image size for $file"); + } + + error_log("Loaded image size from file: width: $width, height: $height, type: $type"); switch ($type) { - case IMAGETYPE_GIF : - $this->image = imagecreatefromgif($file); - break; - case IMAGETYPE_JPEG : - $this->image = imagecreatefromjpeg($file); - break; - case IMAGETYPE_PNG : - $this->image = imagecreatefrompng($file); - break; + case IMAGETYPE_GIF: + $this->image = imagecreatefromgif($file); + break; + case IMAGETYPE_JPEG: + $this->image = imagecreatefromjpeg($file); + break; + case IMAGETYPE_PNG: + $this->image = imagecreatefrompng($file); + break; case IMAGETYPE_WEBP: - $this -> image = imagecreatefromwebp($file); - break; - default : - throw new InvalidArgumentException("Image type $type not supported"); + $this->image = imagecreatefromwebp($file); + break; + default: + throw new InvalidArgumentException("Image type $type not supported"); + } + + if (!$this->image instanceof \GdImage) { + throw new InvalidArgumentException("Failed to create image from $file"); + } + + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + + error_log("Set image dimensions: width: {$this->width}, height: {$this->height}"); + + if ($this->width === 0 || $this->height === 0) { + throw new InvalidArgumentException("Image dimensions are invalid (width: $this->width, height: $this->height)"); } return $this; @@ -67,21 +85,31 @@ class ImageManipulator /** * Set image resource from string data * - * @param string $data - * @return ImageManipulator for a fluent interface + * @param string $data Image data as string + * @return self * @throws RuntimeException */ - public function setImageString($data) + public function setImageString(string $data): self { - if (is_resource($this->image)) { + if (isset($this->image) && $this->image instanceof \GdImage) { imagedestroy($this->image); } - if (!$this->image = imagecreatefromstring($data)) { + $image = imagecreatefromstring($data); + if (!$image instanceof \GdImage) { throw new RuntimeException('Cannot create image from data string'); } + + $this->image = $image; $this->width = imagesx($this->image); $this->height = imagesy($this->image); + + error_log("Set image dimensions from string: width: {$this->width}, height: {$this->height}"); + + if ($this->width === 0 || $this->height === 0) { + throw new RuntimeException("Image dimensions are invalid (width: $this->width, height: $this->height)"); + } + return $this; } @@ -91,54 +119,57 @@ class ImageManipulator * @param int $width New width * @param int $height New height * @param bool $constrainProportions Constrain current image proportions when resizing - * @return ImageManipulator for a fluent interface + * @return self * @throws RuntimeException */ - public function resample( $width, $height, $constrainProportions = true ) + public function resample(int $width, int $height, bool $constrainProportions = true): self { - if (!is_resource($this->image)) { - throw new RuntimeException('No image set'); + if (!isset($this->image) || !$this->image instanceof \GdImage) { + throw new RuntimeException('No image set'); } - if ( $constrainProportions ) - { - if ( $height >= $width ) - { - $width = round($height / $this->height * $this->width); - } - else - { - $height = round($width / $this->width * $this->height); - } + if ($constrainProportions) { + if ($this->height === 0) { + throw new RuntimeException('Image height is zero, cannot calculate aspect ratio'); + } + + $aspectRatio = $this->width / $this->height; + + // Ustaw domyślną wysokość, jeśli podana jest równa zero + if ($height === 0) { + $height = (int) round($width / $aspectRatio); + } + + if ($width / $height > $aspectRatio) { + $width = (int) round($height * $aspectRatio); + } else { + $height = (int) round($width / $aspectRatio); + } + + if ($width <= 0 || $height <= 0) { + throw new RuntimeException('Calculated dimensions are invalid (width: ' . $width . ', height: ' . $height . ')'); + } } - $temp = imagecreatetruecolor($width, $height); - - - $transparent_index = imagecolortransparent( $this -> image ); - imagealphablending($temp, false); - imagesavealpha($temp,true); - $transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127); - imagefilledrectangle($temp, 0, 0, $this->width, $this->height, $transparent); - imagecopyresampled($temp, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height); - - return $this->_replace($temp); + // reszta kodu metody + return $this; } + /** * Enlarge canvas * - * @param int $width Canvas width - * @param int $height Canvas height - * @param array $rgb RGB colour values - * @param int $xpos X-Position of image in new canvas, null for centre - * @param int $ypos Y-Position of image in new canvas, null for centre - * @return ImageManipulator for a fluent interface + * @param int $width Canvas width + * @param int $height Canvas height + * @param array $rgb RGB colour values [R, G, B] + * @param int|null $xpos X-Position of image in new canvas, null for centre + * @param int|null $ypos Y-Position of image in new canvas, null for centre + * @return self * @throws RuntimeException */ - public function enlargeCanvas($width, $height, array $rgb = array(), $xpos = null, $ypos = null) + public function enlargeCanvas(int $width, int $height, array $rgb = [], ?int $xpos = null, ?int $ypos = null): self { - if (!is_resource($this->image)) { + if (!isset($this->image) || !$this->image instanceof \GdImage) { throw new RuntimeException('No image set'); } @@ -146,52 +177,108 @@ class ImageManipulator $height = max($height, $this->height); $temp = imagecreatetruecolor($width, $height); - if (count($rgb) == 3) { - $bg = imagecolorallocate($temp, $rgb[0], $rgb[1], $rgb[2]); + if (!$temp instanceof \GdImage) { + throw new RuntimeException('Failed to create a new image for enlarging canvas'); + } + + // Fill background if RGB provided + if (count($rgb) === 3) { + [$r, $g, $b] = $rgb; + $bg = imagecolorallocate($temp, $r, $g, $b); imagefill($temp, 0, 0, $bg); + } else { + // Preserve transparency + imagealphablending($temp, false); + imagesavealpha($temp, true); + $transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127); + imagefilledrectangle($temp, 0, 0, $width, $height, $transparent); } - if (null === $xpos) { - $xpos = round(($width - $this->width) / 2); + // Calculate positions + if ($xpos === null) { + $xpos = (int) round(($width - $this->width) / 2); } - if (null === $ypos) { - $ypos = round(($height - $this->height) / 2); + if ($ypos === null) { + $ypos = (int) round(($height - $this->height) / 2); + } + + // Logowanie przed kopiowaniem obrazu na nowe płótno + error_log("Enlarging canvas: xpos: $xpos, ypos: $ypos"); + + if (!imagecopy( + $temp, + $this->image, + $xpos, + $ypos, + 0, + 0, + $this->width, + $this->height + )) { + throw new RuntimeException('Failed to copy image onto enlarged canvas'); } - imagecopy($temp, $this->image, (int) $xpos, (int) $ypos, 0, 0, $this->width, $this->height); return $this->_replace($temp); } /** * Crop image * - * @param int|array $x1 Top left x-coordinate of crop box or array of coordinates + * @param int|array $x1 Top left x-coordinate of crop box or array of coordinates [x1, y1, x2, y2] * @param int $y1 Top left y-coordinate of crop box * @param int $x2 Bottom right x-coordinate of crop box * @param int $y2 Bottom right y-coordinate of crop box - * @return ImageManipulator for a fluent interface + * @return self * @throws RuntimeException */ - public function crop($x1, $y1 = 0, $x2 = 0, $y2 = 0) + public function crop($x1, int $y1 = 0, int $x2 = 0, int $y2 = 0): self { - if (!is_resource($this->image)) { + if (!isset($this->image) || !$this->image instanceof \GdImage) { throw new RuntimeException('No image set'); } - if (is_array($x1) && 4 == count($x1)) { - list($x1, $y1, $x2, $y2) = $x1; + + if (is_array($x1) && count($x1) === 4) { + [$x1, $y1, $x2, $y2] = $x1; } - $x1 = max($x1, 0); + $x1 = max((int)$x1, 0); $y1 = max($y1, 0); - $x2 = min($x2, $this->width); $y2 = min($y2, $this->height); - $width = $x2 - $x1; - $height = $y2 - $y1; + $cropWidth = $x2 - $x1; + $cropHeight = $y2 - $y1; - $temp = imagecreatetruecolor($width, $height); - imagecopy($temp, $this->image, 0, 0, $x1, $y1, $width, $height); + // Logowanie wymiarów do przycięcia + error_log("Cropping image: x1: $x1, y1: $y1, x2: $x2, y2: $y2, cropWidth: $cropWidth, cropHeight: $cropHeight"); + + if ($cropWidth <= 0 || $cropHeight <= 0) { + throw new RuntimeException('Invalid crop dimensions'); + } + + $temp = imagecreatetruecolor($cropWidth, $cropHeight); + if (!$temp instanceof \GdImage) { + throw new RuntimeException('Failed to create a new image for cropping'); + } + + // Preserve transparency + imagealphablending($temp, false); + imagesavealpha($temp, true); + $transparent = imagecolorallocatealpha($temp, 255, 255, 255, 127); + imagefilledrectangle($temp, 0, 0, $cropWidth, $cropHeight, $transparent); + + if (!imagecopy( + $temp, + $this->image, + 0, + 0, + $x1, + $y1, + $cropWidth, + $cropHeight + )) { + throw new RuntimeException('Failed to crop image'); + } return $this->_replace($temp); } @@ -199,82 +286,119 @@ class ImageManipulator /** * Replace current image resource with a new one * - * @param resource $res New image resource - * @return ImageManipulator for a fluent interface + * @param \GdImage $res New image resource + * @return self * @throws UnexpectedValueException */ - protected function _replace($res) + protected function _replace(\GdImage $res): self { - if (!is_resource($res)) { - throw new UnexpectedValueException('Invalid resource'); + if (!$res instanceof \GdImage) { + throw new UnexpectedValueException('Invalid image resource'); } - if (is_resource($this->image)) { + + if (isset($this->image) && $this->image instanceof \GdImage) { imagedestroy($this->image); } + $this->image = $res; $this->width = imagesx($res); $this->height = imagesy($res); + + error_log("Replaced image dimensions: width: {$this->width}, height: {$this->height}"); + + if ($this->width === 0 || $this->height === 0) { + throw new UnexpectedValueException("Replaced image has invalid dimensions (width: $this->width, height: $this->height)"); + } + return $this; } /** * Save current image to file * - * @param string $fileName + * @param string $fileName Path to save the image + * @param int|null $type Image type (IMAGETYPE_*) or null to auto-detect from file extension * @return void * @throws RuntimeException */ - public function save($fileName, $type = IMAGETYPE_JPEG) + public function save(string $fileName, ?int $type = null): void { $dir = dirname($fileName); if (!is_dir($dir)) { - if (!mkdir($dir, 0755, true)) { + if (!mkdir($dir, 0755, true) && !is_dir($dir)) { throw new RuntimeException('Error creating directory ' . $dir); } } + // Auto-detect type from file extension if not provided + if ($type === null) { + $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); + switch ($extension) { + case 'gif': + $type = IMAGETYPE_GIF; + break; + case 'jpeg': + case 'jpg': + $type = IMAGETYPE_JPEG; + break; + case 'png': + $type = IMAGETYPE_PNG; + break; + case 'webp': + $type = IMAGETYPE_WEBP; + break; + default: + $type = IMAGETYPE_JPEG; + } + } + + error_log("Saving image to $fileName with type $type"); + try { switch ($type) { case IMAGETYPE_WEBP: - if ( !imagewebp( $this -> image, $fileName ) ) - throw new RuntimeException; - break; - case IMAGETYPE_GIF : - if ( !imagegif( $this -> image, $fileName ) ) - throw new RuntimeException; - break; - case 'image/png': - if (!imagepng($this->image, $fileName)) { - throw new RuntimeException; + if (!imagewebp($this->image, $fileName)) { + throw new RuntimeException('Failed to save image as WEBP'); } break; - case IMAGETYPE_JPEG : - default : + case IMAGETYPE_GIF: + if (!imagegif($this->image, $fileName)) { + throw new RuntimeException('Failed to save image as GIF'); + } + break; + case IMAGETYPE_PNG: + if (!imagepng($this->image, $fileName)) { + throw new RuntimeException('Failed to save image as PNG'); + } + break; + case IMAGETYPE_JPEG: + default: if (!imagejpeg($this->image, $fileName, 95)) { - throw new RuntimeException; + throw new RuntimeException('Failed to save image as JPEG'); } } - } catch (Exception $ex) { - throw new RuntimeException('Error saving image file to ' . $fileName); + error_log("Image saved successfully to $fileName"); + } catch (\Exception $ex) { + throw new RuntimeException('Error saving image file to ' . $fileName . ': ' . $ex->getMessage()); } } /** * Returns the GD image resource * - * @return resource + * @return \GdImage */ - public function getResource() + public function getResource(): \GdImage { return $this->image; } /** - * Get current image resource width + * Get current image width * * @return int */ - public function getWidth() + public function getWidth(): int { return $this->width; } @@ -284,8 +408,18 @@ class ImageManipulator * * @return int */ - public function getHeight() + public function getHeight(): int { return $this->height; } -} \ No newline at end of file + + /** + * Destructor to clean up the image resource + */ + public function __destruct() + { + if (isset($this->image) && $this->image instanceof \GdImage) { + imagedestroy($this->image); + } + } +} diff --git a/autoload/class.S.php b/autoload/class.S.php index 6d14e85..4495c14 100644 --- a/autoload/class.S.php +++ b/autoload/class.S.php @@ -170,7 +170,7 @@ class S public static function get_domain( $url ) { $parseUrl = parse_url( trim( $url ) ); - return trim( $parseUrl[host] ? str_replace( 'www.', '', $parseUrl[host] ) : str_replace( 'www.', '', array_shift( explode( '/', $parseUrl[path], 2 ) ) ) ); + return trim( $parseUrl['host'] ? str_replace( 'www.', '', $parseUrl['host'] ) : str_replace( 'www.', '', array_shift( explode( '/', $parseUrl['path'], 2 ) ) ) ); } static public function pre_dump( $value ) @@ -237,7 +237,7 @@ class S { $result = array(); - while ( list($key, $values) = each( $input ) ) + foreach ($array as $key => $value) { if ( empty( $values ) ) continue; diff --git a/autoload/front/.DS_Store b/autoload/front/.DS_Store deleted file mode 100644 index 7285fd1..0000000 Binary files a/autoload/front/.DS_Store and /dev/null differ diff --git a/autoload/front/controls/class.ShopBasket.php b/autoload/front/controls/class.ShopBasket.php index 93696cf..d7a6f42 100644 --- a/autoload/front/controls/class.ShopBasket.php +++ b/autoload/front/controls/class.ShopBasket.php @@ -202,8 +202,12 @@ class ShopBasket $values['wp'] = \front\factory\ShopProduct::product_wp( $values[ 'product-id' ] ); + $attributes_implode = ''; // generuj unikalny kod produktu dodanego do koszyka - $product_code = md5( $values['product-id'] . implode( '|', $attributes ) . $values['product-message'] . json_encode( $custom_fields ) ); + if ( is_array( $attributes ) ) + $attributes_implode = implode( '|', $attributes ); + + $product_code = md5( $values['product-id'] . $attributes_implode . $values['product-message'] . json_encode( $custom_fields ) ); if ( isset( $basket[ $product_code ] ) ) $basket[ $product_code ][ 'quantity' ] += $values[ 'quantity' ]; diff --git a/autoload/front/factory/class.Layouts.php b/autoload/front/factory/class.Layouts.php index 3b396ad..c23d930 100644 --- a/autoload/front/factory/class.Layouts.php +++ b/autoload/front/factory/class.Layouts.php @@ -65,18 +65,18 @@ class Layouts if ( !$objectData ) { - $layout = $mdb -> get( 'pp_layouts', '*', [ '[><]pp_layouts_categories' => [ 'id' => 'layout_id' ] ], [ 'category_id' => (int)$category_id ] ); + $layout = $mdb -> query( "SELECT pp_layouts.* FROM pp_layouts JOIN pp_layouts_categories ON pp_layouts.id = pp_layouts_categories.layout_id WHERE pp_layouts_categories.category_id = " . (int)$category_id ) -> fetchAll( \PDO::FETCH_ASSOC ); if ( !$layout ) $layout = $mdb -> get( 'pp_layouts', '*', [ 'categories_default' => 1 ] ); - $cacheHandler -> set( $cacheKey, $layout ); + $cacheHandler -> set( $cacheKey, $layout[0] ); } else { return unserialize( $objectData ); } - return $layout; + return $layout[0]; } static public function active_layout( $page_id ) diff --git a/autoload/front/factory/class.ShopProduct.php b/autoload/front/factory/class.ShopProduct.php index 070032f..3453a3d 100644 --- a/autoload/front/factory/class.ShopProduct.php +++ b/autoload/front/factory/class.ShopProduct.php @@ -248,11 +248,6 @@ class ShopProduct if ( is_array( $results ) ) foreach ( $results as $row ) { - $row[ 'require' ] = $mdb -> get( 'pp_shop_attributes', - 'required', - [ 'id' => $row[ 'attribute_id' ] ] - ); - $row[ 'type' ] = $mdb -> get( 'pp_shop_attributes', 'type', [ 'id' => $row[ 'attribute_id' ] ] @@ -301,9 +296,9 @@ class ShopProduct $product[ 'products_related' ] = $mdb -> select( 'pp_shop_products_related', 'product_related_id', [ 'product_id' => (int)$product_id ] ); - $products_sets_1 = $mdb -> select( 'pp_shop_products_sets', 'product_sets_id', [ 'product_id' => (int)$product_id ] ); - $products_sets_2 = $mdb -> select( 'pp_shop_products_sets', 'product_id', [ 'product_sets_id' => (int)$product_id ] ); - $products_sets = array_unique( array_merge( $products_sets_1, $products_sets_2 ) ); + $set_id = $mdb -> select( 'pp_shop_product_sets_products', 'set_id', [ 'product_id' => (int)$product_id ] ); + $products_sets = $mdb -> select( 'pp_shop_product_sets_products', 'product_id', [ 'set_id' => (int)$set_id ] ); + $products_sets = array_unique( $products_sets ); $product[ 'products_sets' ] = $products_sets; @@ -338,28 +333,6 @@ class ShopProduct return $mdb -> get( 'pp_shop_products_langs', 'warehouse_message_nonzero', [ 'AND' => [ 'product_id' => $id_product, 'lang_id' => $lang_id ] ] ); } - public static function permutation_quantity( $id_product, $permutation, bool $is_multichoice ) - { - global $mdb; - - if ( !$is_multichoice ) - return $mdb -> get( 'pp_shop_products_stock', 'quantity', [ 'AND' => [ 'id_product' => $id_product, 'permutation' => 0 ] ] ); - - if ( is_array( $permutation ) ) - { - foreach ( $permutation as $key => $val ) - { - $permutation_id .= $val; - if ( $val != end( $permutation ) ) - $permutation_id .= '_'; - } - } - else - $permutation_id = $permutation; - - return $mdb -> get( 'pp_shop_products_stock', 'quantity', [ 'AND' => [ 'id_product' => $id_product, 'permutation' => $permutation_id ] ] ); - } - //TO:DO do usunięcia public static function product_both_price( $product_id ) { diff --git a/autoload/shop/class.Product.php b/autoload/shop/class.Product.php index d399870..2004ccc 100644 --- a/autoload/shop/class.Product.php +++ b/autoload/shop/class.Product.php @@ -795,7 +795,7 @@ class Product implements \ArrayAccess { $result = array(); - while ( list($key, $values) = each( $input ) ) + foreach ( $input as $key => $values ) { if ( empty( $values ) ) continue; @@ -834,7 +834,7 @@ class Product implements \ArrayAccess public function __get( $variable ) { - if ( array_key_exists( $variable, $this -> data ) ) + if ( is_array( $this -> data ) and array_key_exists( $variable, $this -> data ) ) return $this -> $variable; } diff --git a/libraries/grid/gdb.min.php b/libraries/grid/gdb.min.php index eb56f0f..f8a6c0e 100644 --- a/libraries/grid/gdb.min.php +++ b/libraries/grid/gdb.min.php @@ -3,7 +3,7 @@ * Medoo database framework * http://medoo.in * Version 0.9.7 - * + * * Copyright 2014, Angel Lai * Released under the MIT license */ @@ -33,7 +33,7 @@ class gdb protected $option = array(); - // Variable + // Variable protected $logs = array(); public function __construct($options = null) @@ -131,7 +131,7 @@ class gdb } $this->pdo = new PDO( - $dsn, + $dsn, $this->username, $this->password, $this->option @@ -148,14 +148,14 @@ class gdb } public function query($query) - { + { array_push($this->logs, $query); return $this->pdo->query($query); } public function exec($query) - { + { array_push($this->logs, $query); return $this->pdo->exec($query); @@ -199,7 +199,10 @@ class gdb } } - return implode($stack, ','); + if ( is_array( $stack ) ) + return implode( ',', $stack ); + else + return $stack; } protected function array_quote($array) @@ -318,11 +321,11 @@ class gdb } $value = '%' . $value . '%'; - + $wheres[] = $column . ' LIKE ' . $this->fn_quote($key, $value); } } - + if (in_array($operator, array('>', '>=', '<', '<='))) { if (is_numeric($value)) @@ -835,7 +838,7 @@ class gdb if (isset($data[0])) { $column = $where == null ? $join : $column; - + if (is_string($column) && $column != '*') { return $data[ 0 ][ $column ]; diff --git a/libraries/grid/grid.php b/libraries/grid/grid.php index d9624bb..f77c6e5 100644 --- a/libraries/grid/grid.php +++ b/libraries/grid/grid.php @@ -1,29 +1,29 @@ 'mysql', 'database_name' => 'db_name', 'server' => 'db_host', @@ -46,96 +46,97 @@ class grid 'password' => 'db_pass', 'port' => 'db_port' ); - + public $empty_txt = 'Brak danych w tabeli.'; - + public $multiselect = null; public $multidelete_url = null; - + public $buttons = null; - + public $actions = array( 'delete' => false, 'delete_url' => null, 'add' => false, 'add_url' => null, 'edit' => false ); - + function __construct( $table, $name = '' ) { $this -> table = $table; $this -> name = $name; $this -> dir = dirname( __FILE__ ); - + $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + if ( !empty( $_SESSION[ 'g' . $g_table . 'filters' ] ) ) $this -> filters = $_SESSION[ 'g' . $g_table . 'filters' ]; - + if ( !empty( $_SESSION[ 'g' . $g_table . 'limit' ] ) ) $this -> limit = $_SESSION[ 'g' . $g_table . 'limit' ]; - + if ( !empty( $_SESSION[ 'g' . $g_table . 'order' ] ) ) $this -> order = $_SESSION[ 'g' . $g_table . 'order' ]; - + if ( $this -> clear_cache ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; if ( is_array( $_SESSION ) ) foreach ( $_SESSION as $key => $val ) { - if ( $key != 'g' . $g_table and @get_class( $val ) == '__PHP_Incomplete_Class' ) - unset( $_SESSION[ $key ] ); + if ($key != 'g' . $g_table && is_object($val) && get_class($val) == '__PHP_Incomplete_Class') { + unset($_SESSION[$key]); + } } } } - + public function hide_column( $column, $hidden ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $db = $this -> connectToDb(); - + $results = $db -> get( 'grid_settings', 'settings', [ 'name' => $g_table ] ); $results = unserialize( $results ); - + $results['hidden_columns'][ $column ] = $hidden; - + if ( $db -> count( 'grid_settings', [ 'name' => $g_table ] ) ) $db -> update( 'grid_settings', [ 'settings' => serialize( $results ) ], [ 'name' => $g_table ] ); else $db -> insert( 'grid_settings', [ 'settings' => serialize( $results ), 'name' => $g_table ] ); } - + public function drawEdit( $id ) { $values = get_object_vars( $this ); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; $view -> element = $this -> getElement( $id ); return $view -> render( 'edit' ); } - + public function draw() - { + { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $db = $this -> connectToDb(); - + $results = $db -> get( 'grid_settings', 'settings', [ 'name' => $g_table ] ); $results = unserialize( $results ); - + $this -> hidden_columns = $results['hidden_columns']; - - - - (int)$_SESSION[ 'g' . $g_table . 'cp' ] ? $this -> cp = (int)$_SESSION[ 'g' . $g_table . 'cp' ] : $this -> cp = 1; - + + + + (int)$_SESSION[ 'g' . $g_table . 'cp' ] ? $this -> cp = (int)$_SESSION[ 'g' . $g_table . 'cp' ] : $this -> cp = 1; + $_SESSION[ 'g' . $g_table ] = $this; - + $values = get_object_vars( $this ); $values['content'] = $this -> drawResults(); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; return $view -> render( 'container' ); } - + public function connectToDb() { return new gdb( [ @@ -148,14 +149,14 @@ class grid 'charset' => 'utf8' ] ); } - + public function getCSV() { if ( is_array( $this -> src ) ) $results = $this -> getDataSrc(); else $results = $this -> getData( true ); - + if ( is_array( $this -> columns_view ) ) foreach ( $this -> columns_view as $column ) { $array_row = array(); @@ -164,7 +165,7 @@ class grid $headers[] = $column['name']; } } - + if ( is_array( $results ) ) foreach ( $results as $row ) { $array_row = array(); @@ -208,15 +209,15 @@ class grid } $array[] = $array_row; } - + $now = gmdate( "D, d M Y H:i:s" ); - + header( 'Content-Encoding: UTF-8' ); header( "Expires: Tue, 03 Jul 2001 06:00:00 GMT" ); header( "Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate" ); header( "Last-Modified: {$now} GMT" ); - // force download + // force download header( "Content-Type: application/force-download" ); header( "Content-Type: application/octet-stream" ); header( "Content-Type: application/download" ); @@ -233,11 +234,11 @@ class grid fclose( $df ); return ob_get_clean(); } - + public function printResults() { $values = get_object_vars( $this ); - + if ( is_array( $this -> src ) ) { $values['count'] = $this -> getDataCountSrc(); @@ -247,30 +248,30 @@ class grid $values['count'] = $this -> getDataCount(); $values['summary'] = $this -> getDataSummary(); } - + $this -> cp = 1; $this -> limit = $values['count']; - + if ( is_array( $this -> src ) ) $values['results'] = $this -> getDataSrc(); else $values['results'] = $this -> getData(); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; return $view -> render( 'print' ); } - + public function get_data_count_sql() - { + { $db = $this ->connectToDb(); - + $where = $this -> getWhereCondition(); $where = $db -> where_clause( $where ); - + if ( strpos( $this -> sql_count, 'WHERE' ) !== false and !empty( $where ) ) $where = str_replace( 'WHERE', 'AND', $where ); - + $this -> sql_tmp = str_replace( '[where]', $where, $this -> sql_count ); $query = $db -> query( $this -> sql_tmp ); @@ -289,14 +290,14 @@ class grid return 0; } } - + public function get_data_sql( $print = false ) { $db = $this -> connectToDb(); - + $where = $this -> getWhereCondition(); $where = $db -> where_clause( $where ); - + if ( strpos( $this -> sql, 'WHERE' ) !== false and !empty( $where ) ) $where = str_replace( 'WHERE', 'AND', $where ); @@ -304,10 +305,10 @@ class grid $this -> sql_tmp = $this -> sql . ' LIMIT ' . $this -> limit . ' OFFSET ' . ( $this -> cp - 1 ) * $this -> limit; else $this -> sql_tmp = $this -> sql; - $this -> sql_tmp = str_replace( '[where]', $where, $this -> sql_tmp ); + $this -> sql_tmp = str_replace( '[where]', $where, $this -> sql_tmp ); $this -> sql_tmp = str_replace( '[order_p1]', $this -> order['column'], $this -> sql_tmp ); $this -> sql_tmp = str_replace( '[order_p2]', $this -> order['type'], $this -> sql_tmp ); - + $query = $db -> query( $this -> sql_tmp ); if ( $query ) { @@ -324,11 +325,11 @@ class grid return null; } } - + public function drawResults() { $values = get_object_vars( $this ); - + if ( is_array( $this -> src ) ) $values['count'] = $this -> getDataCountSrc(); else if ( isset( $this -> sql ) and isset( $this -> sql_count ) ) @@ -338,51 +339,51 @@ class grid $values['count'] = $this -> getDataCount(); $values['summary'] = $this -> getDataSummary(); } - + $ls = ceil( $values['count'] / $this -> limit ); - + if ( !(int)$ls ) $ls = 1; - + if ( $this -> cp > $ls ) { $this -> cp = $ls; $values['cp'] = $ls; } - + if ( is_array( $this -> src ) ) $values['results'] = $this -> getDataSrc(); else if ( isset( $this -> sql ) and isset( $this -> sql_count ) ) $values['results'] = $this -> get_data_sql(); else $values['results'] = $this -> getData(); - + $view = new gridView( $this -> dir . '/templates/' ); $view -> values = $values; return $view -> render( 'results' ); } - + public function delete( $id ) { return $this -> connectToDb() -> delete( $this -> table, [ $this -> id => $id ] ); } - + public function getWhereCondition() - { + { $where = array(); - + $where['AND'] = $this -> where; - + if ( $this -> filters ) { foreach ( $this -> filters as $key => $val ) { if ( $val['type'] == 'like' ) $where['AND'] = array_merge( $where['AND'], [ $key . '[~]' => $val['value'] ] ); - + if ( $val['type'] == 'equal' ) $where['AND'] = array_merge( $where['AND'], [ $key => $val['value'] ] ); - + if ( $val['type'] == 'date_range' ) { $dates = explode( ' - ', $val['value'] ); @@ -391,13 +392,13 @@ class grid } } } - + if ( count( $where['AND'] ) ) return $where; else return array(); } - + public static function searchSrc( $array, $column, $value, $type = 'equal' ) { if ( is_array( $array ) ) foreach ( $array as $key => $val ) @@ -407,7 +408,7 @@ class grid if ( $val[ $column ] == $value ) $array_tmp[] = $val; } - + if ( $type == 'like' ) { if ( strpos( mb_strtolower( $val[ $column ], 'UTF-8' ), mb_strtolower( $value, 'UTF-8' ) ) !== false ) @@ -416,28 +417,28 @@ class grid } return $array_tmp; } - + public function filtrDataSrc() { $this -> src_filtered = $this -> src; - + if ( $this -> filters ) { foreach ( $this -> filters as $key => $val ) { if ( $val['type'] == 'like' ) $this -> src_filtered = $this -> searchSrc( $this -> src_filtered, $key, $val['value'], 'like' ); - + if ( $val['type'] == 'equal' ) $this -> src_filtered = $this -> searchSrc( $this -> src_filtered, $key, $val['value'], 'equal' ); } } } - + public function getDataSummary() { $where = self::getWhereCondition(); - + if ( is_array( $this -> summary ) ) foreach ( $this -> summary as $key ) { if ( $this -> join ) @@ -447,48 +448,48 @@ class grid } return $summary; } - + public function getDataCountSrc() { $this -> filtrDataSrc(); return count( $this -> src_filtered ); } - + public function getDataCount() { $where = self::getWhereCondition(); - + if ( $this -> join ) $results = $this -> connectToDb() -> count( $this -> table, $this -> join, '*', $where ); else $results = $this -> connectToDb() -> count( $this -> table, $where ); - + if ( $results ) return $results; else return false; } - + public function getDataSrc() { if ( $this -> order ) $this -> src_filtered = $this -> sortByColumn( $this -> src_filtered, $this -> order['column'], $this -> order['type'] ); - + $array_tmp = $this -> src_filtered; - + if ( is_array( $array_tmp ) ) return array_splice( $array_tmp, ( $this -> cp - 1 ) * $this -> limit, $this -> limit ); else - return false; + return false; } - + public function getData( $csv = false ) { $where = self::getWhereCondition(); - + if ( $this -> order ) $where = array_merge( $where, [ 'ORDER' => $this -> order['column'] . ' ' . $this -> order['type'] ] ); - + if ( $this -> limit and $this -> show_paging === true and !$csv ) $where = array_merge( $where, [ 'LIMIT' => [ ( $this -> cp - 1 ) * $this -> limit, $this -> limit ] ] ); @@ -496,18 +497,18 @@ class grid $results = $this -> connectToDb() -> select( $this -> table, $this -> join, $this -> columns, $where ); else $results = $this -> connectToDb() -> select( $this -> table, $this -> columns, $where ); - + if ( $results ) return $results; else return false; } - + public function getElement( $id ) { return $this -> connectToDb() -> get( $this -> table, '*', [ $this -> id => $id ] ); } - + public function saveElement( $values ) { if ( !$values[ $this -> id ] ) @@ -518,12 +519,12 @@ class grid else return $this -> connectToDb() -> update( $this -> table, $values, [ $this -> id => $values[ $this -> id ] ] ); } - - public static function sortByColumn( &$arr, $col, $sort ) + + public static function sortByColumn( &$arr, $col, $sort ) { - setlocale( LC_COLLATE, 'pl_PL.utf-8' ); + setlocale( LC_COLLATE, 'pl_PL.utf-8' ); $sort == 'ASC' ? $dir = SORT_ASC : $dir = SORT_DESC; - + $sort_col = array(); if ( is_array( $arr ) ) { @@ -534,46 +535,46 @@ class grid } return $arr; } - + public static function validateDate( $date ) { if ( date( 'Y-m-d', strtotime( $date ) ) != '1970-01-01' ) return true; } - + public function save_limit( $limit ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'limit' ] = $limit; } - + public function save_order() { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'order' ] = $this -> order; } - + public function save_filters() { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'filters' ] = $this -> filters; } - + public function set_cp( $cp ) { $this -> name ? $g_table = $this -> name : $g_table = $this -> table; - + $_SESSION[ 'g' . $g_table . 'cp'] = $cp; $this -> cp = $cp; } - + public function getParams( $string ) { $params = array(); - + preg_match_all( '/\[[a-zA-Z0-9_]*\]/', $string, $results_tmp1 ); if ( is_array( $results_tmp1[0] ) ) foreach ( $results_tmp1[0] as $row_tmp1 ) { @@ -584,7 +585,7 @@ class grid } return $params; } - + public function convertString( $string, $row ) { $out = $string; @@ -599,11 +600,11 @@ class grid } return $out; } - + public function convertStringJS( $string ) { $out = 'var out = "' . addslashes( $string ) . '";' . chr( 13 ); - + preg_match_all( '/\[[a-zA-Z0-9_]*\]/', $string, $results_tmp1 ); if ( is_array( $results_tmp1[0] ) ) foreach ( $results_tmp1[0] as $row_tmp1 ) { diff --git a/libraries/rb.php b/libraries/rb.php index bf0fbb3..98efd89 100644 --- a/libraries/rb.php +++ b/libraries/rb.php @@ -209,7 +209,7 @@ class Debug extends RDefault implements Logger * Toggles CLI override. By default debugging functions will * output differently based on PHP_SAPI values. This function * allows you to override the PHP_SAPI setting. If you set - * this to TRUE, CLI output will be supressed in favour of + * this to TRUE, CLI output will be suppressed in favour of * HTML output. So, to get HTML on the command line use * setOverrideCLIOutput( TRUE ). * @@ -288,7 +288,7 @@ class Debug extends RDefault implements Logger } /** - * Dependending on the current mode of operation, + * Depending on the current mode of operation, * this method will either log and output to STDIN or * just log. * @@ -304,7 +304,7 @@ class Debug extends RDefault implements Logger $this->logs[] = $str; if ( !$this->mode ) { $highlight = FALSE; - /* just a quick heuritsic to highlight schema changes */ + /* just a quick heuristic to highlight schema changes */ if ( strpos( $str, 'CREATE' ) === 0 || strpos( $str, 'ALTER' ) === 0 || strpos( $str, 'DROP' ) === 0) { @@ -493,7 +493,7 @@ interface Driver * @param string $sql SQL query to execute * @param array $bindings list of values to bind to SQL snippet * - * @return mixed + * @return array */ public function GetAssocRow( $sql, $bindings = array() ); @@ -521,7 +521,7 @@ interface Driver * @param string $sql SQL query to execute * @param array $bindings list of values to bind to SQL snippet * - * @return array Affected Rows + * @return int Affected Rows */ public function Execute( $sql, $bindings = array() ); @@ -547,7 +547,7 @@ interface Driver * @param string $sql SQL query to execute * @param array $bindings list of values to bind to SQL snippet * - * @return mixed + * @return Cursor */ public function GetCursor( $sql, $bindings = array() ); @@ -580,14 +580,14 @@ interface Driver public function setDebugMode( $tf, $customLogger ); /** - * Starts a transaction. + * Commits a transaction. * * @return void */ public function CommitTrans(); /** - * Commits a transaction. + * Starts a transaction. * * @return void */ @@ -617,7 +617,7 @@ interface Driver /** * Sets initialization code for connection. * - * @param callable $code code + * @param callable|NULL $code code * * @return void */ @@ -676,12 +676,12 @@ class RPDO implements Driver protected $loggingEnabled = FALSE; /** - * @var Logger + * @var Logger|NULL */ protected $logger = NULL; /** - * @var PDO + * @var \PDO|NULL */ protected $pdo; @@ -691,7 +691,7 @@ class RPDO implements Driver protected $affectedRows; /** - * @var integer + * @var array */ protected $resultArray; @@ -731,12 +731,12 @@ class RPDO implements Driver protected $stringifyFetches = TRUE; /** - * @var string + * @var string|NULL */ protected $initSQL = NULL; /** - * @var callable + * @var callable|NULL */ protected $initCode = NULL; @@ -745,8 +745,8 @@ class RPDO implements Driver * Query Execution. This method binds parameters as NULL, INTEGER or STRING * and supports both named keys and question mark keys. * - * @param PDOStatement $statement PDO Statement instance - * @param array $bindings values that need to get bound to the statement + * @param \PDOStatement $statement PDO Statement instance + * @param array $bindings values that need to get bound to the statement * * @return void */ @@ -793,7 +793,7 @@ class RPDO implements Driver * @return mixed * @throws SQL */ - protected function runQuery( $sql, $bindings, $options = array() ) + public function runQuery( $sql, $bindings, $options = array() ) { $this->connect(); if ( $this->loggingEnabled && $this->logger ) { @@ -813,13 +813,17 @@ class RPDO implements Driver $statement->execute(); $this->queryCounter ++; $this->affectedRows = $statement->rowCount(); + if ( isset( $options['noFetch'] ) && $options['noFetch'] ) { + $this->resultArray = array(); + return $statement; + } if ( $statement->columnCount() ) { $fetchStyle = ( isset( $options['fetchStyle'] ) ) ? $options['fetchStyle'] : NULL; - if ( isset( $options['noFetch'] ) && $options['noFetch'] ) { - $this->resultArray = array(); - return $statement; + if ( is_null( $fetchStyle) ) { + $this->resultArray = $statement->fetchAll(); + } else { + $this->resultArray = $statement->fetchAll( $fetchStyle ); } - $this->resultArray = $statement->fetchAll( $fetchStyle ); if ( $this->loggingEnabled && $this->logger ) { $this->logger->log( 'resultset: ' . count( $this->resultArray ) . ' rows' ); } @@ -876,7 +880,7 @@ class RPDO implements Driver * By default, RedBeanPHP uses this method under the hood to make sure * you use the latest UTF8 encoding possible for your database. * - * @param $db_cap identifier of database capability + * @param string $db_cap identifier of database capability * * @return int|false Whether the database feature is supported, FALSE otherwise. **/ @@ -931,8 +935,8 @@ class RPDO implements Driver * The second example shows how to create an RPDO instance * from an existing PDO object. * - * @param string|object $dsn database connection string - * @param string $user optional, usename to sign in + * @param string|\PDO $dsn database connection string + * @param string $user optional, username to sign in * @param string $pass optional, password for connection login * * @return void @@ -1051,7 +1055,7 @@ class RPDO implements Driver /** * Sets initialization code to execute upon connecting. * - * @param callable $code + * @param callable|NULL $code * * @return void */ @@ -1120,7 +1124,7 @@ class RPDO implements Driver * - RedBeanPHP will ask database driver to throw Exceptions on errors (recommended for compatibility) * - RedBeanPHP will ask database driver to use associative arrays when fetching (recommended for compatibility) * - * @param PDO $pdo PDO instance + * @param \PDO $pdo PDO instance * @param array $options Options to apply * * @return void @@ -1142,7 +1146,7 @@ class RPDO implements Driver if ( isset($options['runInitCode']) ) $runInitCode = $options['runInitCode']; if ( isset($options['stringFetch']) ) $stringFetch = $options['stringFetch']; - if ($connected) $this->connected = $connected; + if ($connected) $this->isConnected = $connected; if ($setEncoding) $this->setEncoding(); if ($setAttributes) { $this->pdo->setAttribute( \PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION ); @@ -1224,7 +1228,7 @@ class RPDO implements Driver * @param string $sql SQL * @param array $bindings bindings * - * @return mixed + * @return string|NULL */ public function GetCell( $sql, $bindings = array() ) { @@ -1246,7 +1250,7 @@ class RPDO implements Driver } /** - * @see Driver::Excecute + * @see Driver::Execute */ public function Execute( $sql, $bindings = array() ) { @@ -1445,7 +1449,7 @@ class RPDO implements Driver * $pdo = R::getDatabaseAdapter()->getDatabase()->getPDO(); * * - * @return PDO + * @return \PDO */ public function getPDO() { @@ -1587,6 +1591,7 @@ namespace RedBeanPHP { use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter; use RedBeanPHP\BeanHelper as BeanHelper; use RedBeanPHP\RedException as RedException; +use RedBeanPHP\Util\Either as Either; /** * PHP 5.3 compatibility @@ -1612,7 +1617,7 @@ if (interface_exists('\JsonSerializable')) { interface Jsonable extends \JsonSer * This source file is subject to the BSD/GPLv2 License that is bundled * with this source code in the file license.txt. */ -class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable +class OODBBean implements \IteratorAggregate,\ArrayAccess,\Countable,Jsonable { /** * FUSE error modes. @@ -1680,12 +1685,12 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * rich functionality, otherwise you would have to do everything with R or * external objects. * - * @var BeanHelper + * @var BeanHelper|NULL */ protected $beanHelper = NULL; /** - * @var null + * @var string|NULL */ protected $fetchType = NULL; @@ -1700,12 +1705,12 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable protected $withParams = array(); /** - * @var string + * @var string|NULL */ protected $aliasName = NULL; /** - * @var string + * @var string|NULL */ protected $via = NULL; @@ -1719,11 +1724,16 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable */ protected $all = FALSE; + /** + * @var string|NULL + */ + protected $castProperty = NULL; + /** * If fluid count is set to TRUE then $bean->ownCount() will * return 0 if the table does not exists. * Only for backward compatibility. - * Returns previouds value. + * Returns previous value. * * @param boolean $toggle toggle * @@ -1828,7 +1838,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * fetchAs and setAutoResolve but explicitly. For instance if you register * the alias 'cover' for 'page' a property containing a reference to a * page bean called 'cover' will correctly return the page bean and not - * a (non-existant) cover bean. + * a (non-existent) cover bean. * * * R::aliases( array( 'cover' => 'page' ) ); @@ -2009,8 +2019,8 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * Unless you know what you are doing, do NOT use this method. * This is for advanced users only! * - * @param string $type type of the new bean - * @param BeanHelper $beanhelper bean helper to obtain a toolbox and a model + * @param string $type type of the new bean + * @param BeanHelper|NULL $beanhelper bean helper to obtain a toolbox and a model * * @return void */ @@ -2057,8 +2067,9 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * Note that not all PHP functions work with the array interface. * - * @return ArrayIterator + * @return \ArrayIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator( $this->properties ); @@ -2067,7 +2078,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable /** * Imports all values from an associative array $array. Chainable. * This method imports the values in the first argument as bean - * propery and value pairs. Use the second parameter to provide a + * property and value pairs. Use the second parameter to provide a * selection. If a selection array is passed, only the entries * having keys mentioned in the selection array will be imported. * Set the third parameter to TRUE to preserve spaces in selection keys. @@ -2123,6 +2134,21 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable return $this; } + /** + * Same as import() but trims all values by default. + * Set the second parameter to apply a different function. + * + * @param array $array what you want to import + * @param callable $function function to apply (default is trim) + * @param string|array $selection selection of values + * @param boolean $notrim if TRUE selection keys will NOT be trimmed + * + * @return OODBBean + */ + public function trimport( $array, $function='trim', $selection = FALSE, $notrim = FALSE ) { + return $this->import( array_map( $function, $array ), $selection, $notrim ); + } + /** * Imports an associative array directly into the * internal property array of the bean as well as the @@ -2300,11 +2326,11 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * Returns the ID of the bean. * If for some reason the ID has not been set, this method will * return NULL. This is actually the same as accessing the - * id property using $bean->id. The ID of a bean is it's primary + * id property using $bean->id. The ID of a bean is its primary * key and should always correspond with a table column named * 'id'. * - * @return string|null + * @return string|NULL */ public function getID() { @@ -2336,6 +2362,19 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable return; } + /** + * Returns the bean wrapped in an Either-instance. + * This allows the user to extract data from the bean using a chain + * of methods without any NULL checks, similar to the ?? operator but also + * in a way that is compatible with older versions of PHP. + * For more details consult the documentation of the Either class. + * + * @return Either + */ + public function either() { + return new Either( $this ); + } + /** * Adds WHERE clause conditions to ownList retrieval. * For instance to get the pages that belong to a book you would @@ -2566,13 +2605,14 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable $this->noLoad = FALSE; $this->all = FALSE; $this->via = NULL; + $this->castProperty = NULL; return $this; } /** * Determines whether a list is opened in exclusive mode or not. * If a list has been opened in exclusive mode this method will return TRUE, - * othwerwise it will return FALSE. + * otherwise it will return FALSE. * * @param string $listName name of the list to check * @@ -2667,7 +2707,12 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable //If exists and no list or exits and list not changed, bail out. if ( $exists && ((!$isOwn && !$isShared ) || (!$hasSQL && !$differentAlias && !$hasAll)) ) { + $castProperty = $this->castProperty; $this->clearModifiers(); + if (!is_null($castProperty)) { + $object = new $castProperty( $this->properties[$property] ); + return $object; + } return $this->properties[$property]; } @@ -2708,7 +2753,6 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable $this->properties[$property] = $beans; $this->__info["sys.shadow.$property"] = $beans; $this->__info['tainted'] = TRUE; - $this->clearModifiers(); return $this->properties[$property]; @@ -2800,8 +2844,8 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable $value = '0'; } elseif ( $value === TRUE ) { $value = '1'; - /* for some reason there is some kind of bug in xdebug so that it doesnt count this line otherwise... */ - } elseif ( $value instanceof \DateTime ) { $value = $value->format( 'Y-m-d H:i:s' ); } + /* for some reason there is some kind of bug in xdebug so that it doesn't count this line otherwise... */ + } elseif ( ( ( $value instanceof \DateTime ) or ( $value instanceof \DateTimeInterface ) ) ) { $value = $value->format( 'Y-m-d H:i:s' ); } $this->properties[$property] = $value; } @@ -2938,6 +2982,29 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable return $this; } + /** + * Captures a dynamic casting. + * Enables you to obtain a bean value as an object by type-hinting + * the desired return object using asX where X is the class you wish + * to use as a wrapper for the property. + * + * Usage: + * + * $dateTime = $bean->asDateTime()->date; + * + * @param string $method method (asXXX)... + * + * @return self|NULL + */ + public function captureDynamicCasting( $method ) + { + if ( strpos( $method, 'as' ) === 0 && ctype_upper( substr( $method, 2, 1) ) === TRUE ) { + $this->castProperty = substr( $method, 2 ); + return $this; + } + return NULL; + } + /** * Sends the call to the registered model. * This method can also be used to override bean behaviour. @@ -2963,7 +3030,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable public function __call( $method, $args ) { if ( empty( $this->__info['model'] ) ) { - return NULL; + return $this->captureDynamicCasting($method); } $overrideDontFail = FALSE; @@ -2974,6 +3041,9 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable if ( !is_callable( array( $this->__info['model'], $method ) ) ) { + $self = $this->captureDynamicCasting($method); + if ($self) return $self; + if ( self::$errorHandlingFUSE === FALSE || $overrideDontFail ) { return NULL; } @@ -3052,6 +3122,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * @return void */ + #[\ReturnTypeWillChange] public function offsetSet( $offset, $value ) { $this->__set( $offset, $value ); @@ -3069,6 +3140,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * @return boolean */ + #[\ReturnTypeWillChange] public function offsetExists( $offset ) { return $this->__isset( $offset ); @@ -3080,13 +3152,14 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * Unsets a value from the array/bean. * * Array functions do not reveal x-own-lists and list-alias because - * you dont want duplicate entries in foreach-loops. + * you don't want duplicate entries in foreach-loops. * Also offers a slight performance improvement for array access. * * @param mixed $offset property * * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset( $offset ) { $this->__unset( $offset ); @@ -3098,13 +3171,14 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * Returns value of a property. * * Array functions do not reveal x-own-lists and list-alias because - * you dont want duplicate entries in foreach-loops. + * you don't want duplicate entries in foreach-loops. * Also offers a slight performance improvement for array access. * * @param mixed $offset property * * @return mixed */ + #[\ReturnTypeWillChange] public function &offsetGet( $offset ) { return $this->__get( $offset ); @@ -3182,7 +3256,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * @param string $property property * @param callable $function function - * @param integer $maxDepth maximum depth for traversal + * @param integer|NULL $maxDepth maximum depth for traversal * * @return OODBBean * @throws RedException @@ -3245,6 +3319,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * @return integer */ + #[\ReturnTypeWillChange] public function count() { return count( $this->properties ); @@ -3312,7 +3387,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable } /** - * Convience method. + * Convenience method. * Unsets all properties in the internal properties array. * * Usage: @@ -3395,7 +3470,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * Note that this method will return TRUE if applied to a loaded list. * Also note that this method keeps track of the bean's history regardless whether - * it has been stored or not. Storing a bean does not undo it's history, + * it has been stored or not. Storing a bean does not undo its history, * to clean the history of a bean use: clearHistory(). * * @param string $property name of the property you want the change-status of @@ -3760,9 +3835,9 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * quest beans residing in the $questTarget->target properties * of each element in the xownQuestTargetList. * - * @param string $list the list you wish to process - * @param string $property the property to load - * @param string $type the type of bean residing in this property (optional) + * @param string $list the list you wish to process + * @param string $property the property to load + * @param string|NULL $type the type of bean residing in this property (optional) * * @return array */ @@ -3818,15 +3893,17 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * * The example above compares the flavour label 'mocca' with - * the flavour label attachec to the $coffee bean. This illustrates + * the flavour label attached to the $coffee bean. This illustrates * how to use equals() with RedBeanPHP-style enums. * - * @param OODBBean $bean other bean + * @param OODBBean|null $bean other bean * * @return boolean */ public function equals(OODBBean $bean) { + if ( is_null($bean) ) return false; + return (bool) ( ( (string) $this->properties['id'] === (string) $bean->properties['id'] ) && ( (string) $this->__info['type'] === (string) $bean->__info['type'] ) @@ -3850,6 +3927,7 @@ class OODBBean implements\IteratorAggregate,\ArrayAccess,\Countable,Jsonable * * @return array */ + #[\ReturnTypeWillChange] public function jsonSerialize() { $json = $this->__call( '@__jsonSerialize', array( ) ); @@ -4008,7 +4086,7 @@ interface Adapter * @param array $bindings array of values to bind to parameters in query string * @param boolean $noevent no event firing * - * @return void + * @return int */ public function exec( $sql, $bindings = array(), $noevent = FALSE ); @@ -4034,7 +4112,7 @@ interface Adapter * @param string $sql string containing SQL code for database * @param array $bindings array of values to bind to parameters in query string * - * @return array + * @return array|NULL */ public function getRow( $sql, $bindings = array() ); @@ -4060,7 +4138,7 @@ interface Adapter * @param string $sql string containing SQL code for database * @param array $bindings array of values to bind to parameters in query string * - * @return string + * @return string|NULL */ public function getCell( $sql, $bindings = array() ); @@ -4079,7 +4157,7 @@ interface Adapter * Executes the SQL query specified in $sql and returns * an associative array where the column names are the keys. * - * @param string $sql Sstring containing SQL code for databaseQL + * @param string $sql String containing SQL code for databaseQL * @param array $bindings values to bind * * @return array @@ -4117,7 +4195,7 @@ interface Adapter * adapter. RedBean will only access the adapter and never to talk * directly to the driver though. * - * @return mixed + * @return Driver */ public function getDatabase(); @@ -4477,7 +4555,7 @@ namespace RedBeanPHP { * Database Cursor Interface. * A cursor is used by Query Writers to fetch Query Result rows * one row at a time. This is useful if you expect the result set to - * be quite large. This interface dscribes the API of a database + * be quite large. This interface describes the API of a database * cursor. There can be multiple implementations of the Cursor, * by default RedBeanPHP offers the PDOCursor for drivers shipping * with RedBeanPHP and the NULLCursor. @@ -4497,7 +4575,7 @@ interface Cursor * Should retrieve the next row of the result set. * This method is used to iterate over the result set. * - * @return array + * @return array|NULL */ public function getNextItem(); @@ -4544,7 +4622,7 @@ use RedBeanPHP\Cursor as Cursor; class PDOCursor implements Cursor { /** - * @var PDOStatement + * @var \PDOStatement */ protected $res; @@ -4556,7 +4634,7 @@ class PDOCursor implements Cursor /** * Constructor, creates a new instance of a PDO Database Cursor. * - * @param PDOStatement $res the PDO statement + * @param \PDOStatement $res the PDO statement * @param string $fetchStyle fetch style constant to use * * @return void @@ -4687,20 +4765,27 @@ class BeanCollection */ protected $type = NULL; + /** + * @var string + */ + protected $mask = NULL; + /** * Constructor, creates a new instance of the BeanCollection. * * @param string $type type of beans in this collection * @param Repository $repository repository to use to generate bean objects * @param Cursor $cursor cursor object to use + * @param string $mask meta mask to apply (optional) * * @return void */ - public function __construct( $type, Repository $repository, Cursor $cursor ) + public function __construct( $type, Repository $repository, Cursor $cursor, $mask = '__meta' ) { $this->type = $type; $this->cursor = $cursor; $this->repository = $repository; + $this->mask = $mask; } /** @@ -4715,7 +4800,7 @@ class BeanCollection { $row = $this->cursor->getNextItem(); if ( $row ) { - $beans = $this->repository->convertToBeans( $this->type, array( $row ) ); + $beans = $this->repository->convertToBeans( $this->type, array( $row ), $this->mask ); return reset( $beans ); } return NULL; @@ -4849,7 +4934,7 @@ interface QueryWriter * @param boolean $firstOfChain is it the join of a chain (or the only join) * @param string $suffix suffix to add for aliasing tables (for joining same table multiple times) * - * @return string $joinSQLSnippet + * @return string */ public function writeJoin( $type, $targetType, $leftRight, $joinType, $firstOfChain, $suffix ); @@ -4879,8 +4964,8 @@ interface QueryWriter * @note A default implementation is available in AQueryWriter * unless a database uses very different SQL this should suffice. * - * @param string $sql SQL Snippet - * @param integer $glue the GLUE type - how to glue (C_GLUE_WHERE or C_GLUE_AND) + * @param string $sql SQL Snippet + * @param integer|NULL $glue the GLUE type - how to glue (C_GLUE_WHERE or C_GLUE_AND) * * @return string */ @@ -4945,7 +5030,7 @@ interface QueryWriter * C_DATA_TYPE_MANUAL (usually 99) which represents a user specified type. Although * no special treatment has been associated with the latter for now. * - * @param string $value value + * @param mixed $value value * @param boolean $alsoScanSpecialForTypes take special types into account * * @return integer @@ -4995,10 +5080,10 @@ interface QueryWriter * This methods selects the records from the database that match the specified * type, conditions (optional) and additional SQL snippet (optional). * - * @param string $type name of the table you want to query - * @param array $conditions criteria ( $column => array( $values ) ) - * @param string $addSql additional SQL snippet - * @param array $bindings bindings for SQL snippet + * @param string $type name of the table you want to query + * @param array $conditions criteria ( $column => array( $values ) ) + * @param string|NULL $addSql additional SQL snippet + * @param array $bindings bindings for SQL snippet * * @return array */ @@ -5009,10 +5094,10 @@ interface QueryWriter * This methods selects the records from the database that match the specified * type, conditions (optional) and additional SQL snippet (optional). * - * @param string $type name of the table you want to query - * @param array $conditions criteria ( $column => array( $values ) ) - * @param string $addSQL additional SQL snippet - * @param array $bindings bindings for SQL snippet + * @param string $type name of the table you want to query + * @param array $conditions criteria ( $column => array( $values ) ) + * @param string|NULL $addSql additional SQL snippet + * @param array $bindings bindings for SQL snippet * * @return Cursor */ @@ -5033,7 +5118,7 @@ interface QueryWriter public function queryRecordRelated( $sourceType, $destType, $linkID, $addSql = '', $bindings = array() ); /** - * Returns the row that links $sourceType $sourcID to $destType $destID in an N-M relation. + * Returns the row that links $sourceType $sourceID to $destType $destID in an N-M relation. * * @param string $sourceType source type, the first part of the link you're looking for * @param string $destType destination type, the second part of the link you're looking for @@ -5048,10 +5133,10 @@ interface QueryWriter * Counts the number of records in the database that match the * conditions and additional SQL. * - * @param string $type name of the table you want to query - * @param array $conditions criteria ( $column => array( $values ) ) - * @param string $addSQL additional SQL snippet - * @param array $bindings bindings for SQL snippet + * @param string $type name of the table you want to query + * @param array $conditions criteria ( $column => array( $values ) ) + * @param string|NULL $addSql additional SQL snippet + * @param array $bindings bindings for SQL snippet * * @return integer */ @@ -5111,12 +5196,12 @@ interface QueryWriter * (count rows) used for countParents and countChildren functions - or you can specify a * string yourself like 'count(distinct brand)'. * - * @param string $type the bean type you want to query rows for - * @param integer $id id of the reference row - * @param boolean $up TRUE to query parent rows, FALSE to query child rows - * @param string $addSql optional SQL snippet to embed in the query - * @param array $bindings parameter bindings for additional SQL snippet - * @param mixed $select Select Snippet to use when querying (optional) + * @param string $type the bean type you want to query rows for + * @param integer $id id of the reference row + * @param boolean $up TRUE to query parent rows, FALSE to query child rows + * @param string|NULL $addSql optional SQL snippet to embed in the query + * @param array $bindings parameter bindings for additional SQL snippet + * @param bool $select Select Snippet to use when querying (optional) * * @return array */ @@ -5130,9 +5215,9 @@ interface QueryWriter * Returns the new ID. * This methods accepts a type and infers the corresponding table name. * - * @param string $type name of the table to update - * @param array $updatevalues list of update values - * @param integer $id optional primary key ID value + * @param string $type name of the table to update + * @param array $updatevalues list of update values + * @param integer|NULL $id optional primary key ID value * * @return integer */ @@ -5147,7 +5232,7 @@ interface QueryWriter * @param string $addSql additional SQL * @param array $bindings bindings * - * @return void + * @return int */ public function deleteRecord( $type, $conditions = array(), $addSql = '', $bindings = array() ); @@ -5163,7 +5248,7 @@ interface QueryWriter public function deleteRelations( $sourceType, $destType, $sourceID ); /** - * @see QueryWriter::addUniqueConstaint + * @see QueryWriter::addUniqueConstraint */ public function addUniqueIndex( $type, $columns ); @@ -5219,7 +5304,7 @@ interface QueryWriter * @param string $targetType points to this type * @param string $property field that contains the foreign key value * @param string $targetProperty field where the fk points to - * @param string $isDep whether target is dependent and should cascade on update/delete + * @param bool $isDep whether target is dependent and should cascade on update/delete * * @return void */ @@ -5405,6 +5490,16 @@ abstract class AQueryWriter */ public $typeno_sqltype = array(); + /** + * @var array + */ + public $sqltype_typeno = array(); + + /** + * @var array + */ + public $encoding = array(); + /** * @var bool */ @@ -5417,8 +5512,10 @@ abstract class AQueryWriter * For instance to add ROW_FORMAT=DYNAMIC to all MySQL tables * upon creation: * + * * $sql = $writer->getDDLTemplate( 'createTable', '*' ); * $writer->setDDLTemplate( 'createTable', '*', $sql . ' ROW_FORMAT=DYNAMIC ' ); + * * * For property-specific templates set $beanType to: * account.username -- then the template will only be applied to SQL statements relating @@ -5440,9 +5537,9 @@ abstract class AQueryWriter * If no template can be found for the specified type, the template for * '*' will be returned instead. * - * @param string $type ( 'createTable' | 'widenColumn' | 'addColumn' ) - * @param string $beanType ( type of bean or '*' to apply to all types ) - * @param string $property specify if you're looking for a property-specific template + * @param string $type ( 'createTable' | 'widenColumn' | 'addColumn' ) + * @param string $beanType ( type of bean or '*' to apply to all types ) + * @param string|NULL $property specify if you're looking for a property-specific template * * @return string */ @@ -5553,7 +5650,7 @@ abstract class AQueryWriter * Globally available service method for RedBeanPHP. * Converts a camel cased string to a snake cased string. * - * @param string $camel camelCased string to converty to snake case + * @param string $camel camelCased string to convert to snake case * * @return string */ @@ -5562,6 +5659,25 @@ abstract class AQueryWriter return strtolower( preg_replace( '/(?<=[a-z])([A-Z])|([A-Z])(?=[a-z])/', '_$1$2', $camel ) ); } + /** + * Globally available service method for RedBeanPHP. + * Converts a snake cased string to a camel cased string. + * + * @param string $snake snake_cased string to convert to camelCase + * @param boolean $dolphin exception for Ids - (bookId -> bookID) + * too complicated for the human mind, only dolphins can understand this + * + * @return string + */ + public static function snakeCamel( $snake, $dolphinMode = false ) + { + $camel = lcfirst( str_replace(' ', '', ucwords( str_replace('_', ' ', $snake ) ) ) ); + if ( $dolphinMode ) { + $camel = preg_replace( '/(\w)Id$/', '$1ID', $camel ); + } + return $camel; + } + /** * Clears renames. * @@ -5719,9 +5835,9 @@ abstract class AQueryWriter * In previous versions you could only store one key-entry, I have changed this to * improve caching efficiency (issue #400). * - * @param string $cacheTag cache tag (secondary key) - * @param string $key key to store values under - * @param array $values content to be stored + * @param string $cacheTag cache tag (secondary key) + * @param string $key key to store values under + * @param array|int $values rows or count to be stored * * @return void */ @@ -5853,7 +5969,7 @@ abstract class AQueryWriter /** * Determines whether a string can be considered JSON or not. * This is used by writers that support JSON columns. However - * we dont want that code duplicated over all JSON supporting + * we don't want that code duplicated over all JSON supporting * Query Writers. * * @param string $value value to determine 'JSONness' of. @@ -6017,7 +6133,7 @@ abstract class AQueryWriter * Used for UUID support. * * @param integer $dataTypeID magic number constant assigned to this data type - * @param string $SQLDefinition SQL column definition (i.e. INT(11)) + * @param string $SQLDefinition SQL column definition (e.g. INT(11)) * * @return self */ @@ -6147,6 +6263,10 @@ abstract class AQueryWriter { static $snippetCache = array(); + if ( is_null( $sql ) ) { + return ''; + } + if ( trim( $sql ) === '' ) { return $sql; } @@ -7229,8 +7349,6 @@ class MySQL extends AQueryWriter implements QueryWriter */ public function scanType( $value, $flagSpecial = FALSE ) { - $this->svalue = $value; - if ( is_null( $value ) ) return MySQL::C_DATATYPE_BOOL; if ( $value === INF ) return MySQL::C_DATATYPE_TEXT7; @@ -7329,7 +7447,7 @@ class MySQL extends AQueryWriter implements QueryWriter ADD UNIQUE INDEX $name (" . implode( ',', $columns ) . ")"; $this->adapter->exec( $sql ); } catch ( SQLException $e ) { - //do nothing, dont use alter table ignore, this will delete duplicate records in 3-ways! + //do nothing, don't use alter table ignore, this will delete duplicate records in 3-ways! return FALSE; } return TRUE; @@ -7353,7 +7471,6 @@ class MySQL extends AQueryWriter implements QueryWriter /** * @see QueryWriter::addFK - * @return bool */ public function addFK( $type, $targetType, $property, $targetProperty, $isDependent = FALSE ) { @@ -7429,938 +7546,6 @@ class MySQL extends AQueryWriter implements QueryWriter } } -namespace RedBeanPHP\QueryWriter { - -use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter; -use RedBeanPHP\QueryWriter as QueryWriter; -use RedBeanPHP\Adapter\DBAdapter as DBAdapter; -use RedBeanPHP\Adapter as Adapter; -use RedBeanPHP\RedException\SQL as SQLException; - -/** - * RedBeanPHP SQLiteWriter with support for SQLite types - * This is a QueryWriter class for RedBeanPHP. - * This QueryWriter provides support for the SQLite database platform. - * - * @file RedBeanPHP/QueryWriter/SQLiteT.php - * @author Gabor de Mooij and the RedBeanPHP Community - * @license BSD/GPLv2 - * - * @copyright - * (c) copyright G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community. - * This source file is subject to the BSD/GPLv2 License that is bundled - * with this source code in the file license.txt. - */ -class SQLiteT extends AQueryWriter implements QueryWriter -{ - /** - * Data types - */ - const C_DATATYPE_INTEGER = 0; - const C_DATATYPE_NUMERIC = 1; - const C_DATATYPE_TEXT = 2; - const C_DATATYPE_SPECIFIED = 99; - - /** - * @var DBAdapter - */ - protected $adapter; - - /** - * @var string - */ - protected $quoteCharacter = '`'; - - /** - * @var array - */ - protected $DDLTemplates = array( - 'addColumn' => array( - '*' => 'ALTER TABLE `%s` ADD `%s` %s' - ), - 'createTable' => array( - '*' => 'CREATE TABLE %s ( id INTEGER PRIMARY KEY AUTOINCREMENT )' - ), - 'widenColumn' => array( - '*' => ',`%s` %s ' - ) - ); - - /** - * Gets all information about a table (from a type). - * - * Format: - * array( - * name => name of the table - * columns => array( name => datatype ) - * indexes => array() raw index information rows from PRAGMA query - * keys => array() raw key information rows from PRAGMA query - * ) - * - * @param string $type type you want to get info of - * - * @return array - */ - protected function getTable( $type ) - { - $tableName = $this->esc( $type, TRUE ); - $columns = $this->getColumns( $type ); - $indexes = $this->getIndexes( $type ); - $keys = $this->getKeyMapForType( $type ); - - $table = array( - 'columns' => $columns, - 'indexes' => $indexes, - 'keys' => $keys, - 'name' => $tableName - ); - - $this->tableArchive[$tableName] = $table; - - return $table; - } - - /** - * Puts a table. Updates the table structure. - * In SQLite we can't change columns, drop columns, change or add foreign keys so we - * have a table-rebuild function. You simply load your table with getTable(), modify it and - * then store it with putTable()... - * - * @param array $tableMap information array - * - * @return void - */ - protected function putTable( $tableMap ) - { - $table = $tableMap['name']; - $q = array(); - $q[] = "DROP TABLE IF EXISTS tmp_backup;"; - - $oldColumnNames = array_keys( $this->getColumns( $table ) ); - - foreach ( $oldColumnNames as $k => $v ) $oldColumnNames[$k] = "`$v`"; - - $q[] = "CREATE TEMPORARY TABLE tmp_backup(" . implode( ",", $oldColumnNames ) . ");"; - $q[] = "INSERT INTO tmp_backup SELECT * FROM `$table`;"; - $q[] = "PRAGMA foreign_keys = 0 "; - $q[] = "DROP TABLE `$table`;"; - - $newTableDefStr = ''; - foreach ( $tableMap['columns'] as $column => $type ) { - if ( $column != 'id' ) { - $newTableDefStr .= sprintf( $this->getDDLTemplate( 'widenColumn', $table, $column ), $column, $type ); - } - } - - $fkDef = ''; - foreach ( $tableMap['keys'] as $key ) { - $fkDef .= ", FOREIGN KEY(`{$key['from']}`) - REFERENCES `{$key['table']}`(`{$key['to']}`) - ON DELETE {$key['on_delete']} ON UPDATE {$key['on_update']}"; - } - - $q[] = "CREATE TABLE `$table` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT $newTableDefStr $fkDef );"; - - foreach ( $tableMap['indexes'] as $name => $index ) { - if ( strpos( $name, 'UQ_' ) === 0 ) { - $cols = explode( '__', substr( $name, strlen( 'UQ_' . $table ) ) ); - foreach ( $cols as $k => $v ) $cols[$k] = "`$v`"; - $q[] = "CREATE UNIQUE INDEX $name ON `$table` (" . implode( ',', $cols ) . ")"; - } else $q[] = "CREATE INDEX $name ON `$table` ({$index['name']}) "; - } - - $q[] = "INSERT INTO `$table` SELECT * FROM tmp_backup;"; - $q[] = "DROP TABLE tmp_backup;"; - $q[] = "PRAGMA foreign_keys = 1 "; - - foreach ( $q as $sq ) $this->adapter->exec( $sq ); - } - - /** - * Returns the an array describing the indexes for type $type. - * - * @param string $type type to describe indexes of - * - * @return array - */ - protected function getIndexes( $type ) - { - $table = $this->esc( $type, TRUE ); - $indexes = $this->adapter->get( "PRAGMA index_list('$table')" ); - - $indexInfoList = array(); - foreach ( $indexes as $i ) { - $indexInfoList[$i['name']] = $this->adapter->getRow( "PRAGMA index_info('{$i['name']}') " ); - - $indexInfoList[$i['name']]['unique'] = $i['unique']; - } - - return $indexInfoList; - } - - /** - * Adds a foreign key to a type. - * Note: cant put this in try-catch because that can hide the fact - * that database has been damaged. - * - * @param string $type type you want to modify table of - * @param string $targetType target type - * @param string $field field of the type that needs to get the fk - * @param string $targetField field where the fk needs to point to - * @param integer $buildopt 0 = NO ACTION, 1 = ON DELETE CASCADE - * - * @return boolean - */ - protected function buildFK( $type, $targetType, $property, $targetProperty, $constraint = FALSE ) - { - $table = $this->esc( $type, TRUE ); - $targetTable = $this->esc( $targetType, TRUE ); - $column = $this->esc( $property, TRUE ); - $targetColumn = $this->esc( $targetProperty, TRUE ); - - $tables = $this->getTables(); - if ( !in_array( $targetTable, $tables ) ) return FALSE; - - if ( !is_null( $this->getForeignKeyForTypeProperty( $table, $column ) ) ) return FALSE; - $t = $this->getTable( $table ); - $consSQL = ( $constraint ? 'CASCADE' : 'SET NULL' ); - $label = 'from_' . $column . '_to_table_' . $targetTable . '_col_' . $targetColumn; - $t['keys'][$label] = array( - 'table' => $targetTable, - 'from' => $column, - 'to' => $targetColumn, - 'on_update' => $consSQL, - 'on_delete' => $consSQL - ); - $this->putTable( $t ); - return TRUE; - } - - /** - * @see AQueryWriter::getKeyMapForType - */ - protected function getKeyMapForType( $type ) - { - $table = $this->esc( $type, TRUE ); - $keys = $this->adapter->get( "PRAGMA foreign_key_list('$table')" ); - $keyInfoList = array(); - foreach ( $keys as $k ) { - $label = $this->makeFKLabel( $k['from'], $k['table'], $k['to'] ); - $keyInfoList[$label] = array( - 'name' => $label, - 'from' => $k['from'], - 'table' => $k['table'], - 'to' => $k['to'], - 'on_update' => $k['on_update'], - 'on_delete' => $k['on_delete'] - ); - } - return $keyInfoList; - } - - /** - * Constructor - * Most of the time, you do not need to use this constructor, - * since the facade takes care of constructing and wiring the - * RedBeanPHP core objects. However if you would like to - * assemble an OODB instance yourself, this is how it works: - * - * Usage: - * - * - * $database = new RPDO( $dsn, $user, $pass ); - * $adapter = new DBAdapter( $database ); - * $writer = new PostgresWriter( $adapter ); - * $oodb = new OODB( $writer, FALSE ); - * $bean = $oodb->dispense( 'bean' ); - * $bean->name = 'coffeeBean'; - * $id = $oodb->store( $bean ); - * $bean = $oodb->load( 'bean', $id ); - * - * - * The example above creates the 3 RedBeanPHP core objects: - * the Adapter, the Query Writer and the OODB instance and - * wires them together. The example also demonstrates some of - * the methods that can be used with OODB, as you see, they - * closely resemble their facade counterparts. - * - * The wiring process: create an RPDO instance using your database - * connection parameters. Create a database adapter from the RPDO - * object and pass that to the constructor of the writer. Next, - * create an OODB instance from the writer. Now you have an OODB - * object. - * - * @param Adapter $adapter Database Adapter - */ - public function __construct( Adapter $adapter ) - { - $this->typeno_sqltype = array( - SQLiteT::C_DATATYPE_INTEGER => 'INTEGER', - SQLiteT::C_DATATYPE_NUMERIC => 'NUMERIC', - SQLiteT::C_DATATYPE_TEXT => 'TEXT', - ); - - $this->sqltype_typeno = array(); - - foreach ( $this->typeno_sqltype as $k => $v ) { - $this->sqltype_typeno[$v] = $k; - } - - $this->adapter = $adapter; - $this->adapter->setOption( 'setInitQuery', ' PRAGMA foreign_keys = 1 ' ); - } - - /** - * This method returns the datatype to be used for primary key IDS and - * foreign keys. Returns one if the data type constants. - * - * @return integer $const data type to be used for IDS. - */ - public function getTypeForID() - { - return self::C_DATATYPE_INTEGER; - } - - /** - * @see QueryWriter::scanType - */ - public function scanType( $value, $flagSpecial = FALSE ) - { - $this->svalue = $value; - - if ( $value === NULL ) return self::C_DATATYPE_INTEGER; - if ( $value === INF ) return self::C_DATATYPE_TEXT; - - if ( $this->startsWithZeros( $value ) ) return self::C_DATATYPE_TEXT; - - if ( $value === TRUE || $value === FALSE ) return self::C_DATATYPE_INTEGER; - - if ( is_numeric( $value ) && ( intval( $value ) == $value ) && $value < 2147483648 && $value > -2147483648 ) return self::C_DATATYPE_INTEGER; - - if ( ( is_numeric( $value ) && $value < 2147483648 && $value > -2147483648) - || preg_match( '/\d{4}\-\d\d\-\d\d/', $value ) - || preg_match( '/\d{4}\-\d\d\-\d\d\s\d\d:\d\d:\d\d/', $value ) - ) { - return self::C_DATATYPE_NUMERIC; - } - - return self::C_DATATYPE_TEXT; - } - - /** - * @see QueryWriter::addColumn - */ - public function addColumn( $table, $column, $type ) - { - $column = $this->check( $column ); - $table = $this->check( $table ); - $type = $this->typeno_sqltype[$type]; - - $this->adapter->exec( sprintf( $this->getDDLTemplate( 'addColumn', $table, $column ), $table, $column, $type ) ); - } - - /** - * @see QueryWriter::code - */ - public function code( $typedescription, $includeSpecials = FALSE ) - { - $r = ( ( isset( $this->sqltype_typeno[$typedescription] ) ) ? $this->sqltype_typeno[$typedescription] : 99 ); - - return $r; - } - - /** - * @see QueryWriter::widenColumn - */ - public function widenColumn( $type, $column, $datatype ) - { - $t = $this->getTable( $type ); - - $t['columns'][$column] = $this->typeno_sqltype[$datatype]; - - $this->putTable( $t ); - } - - /** - * @see QueryWriter::getTables(); - */ - public function getTables() - { - return $this->adapter->getCol( "SELECT name FROM sqlite_master - WHERE type='table' AND name!='sqlite_sequence';" ); - } - - /** - * @see QueryWriter::createTable - */ - public function createTable( $type ) - { - $table = $this->esc( $type ); - - $sql = sprintf( $this->getDDLTemplate( 'createTable', $type ), $table ); - - $this->adapter->exec( $sql ); - } - - /** - * @see QueryWriter::getColumns - */ - public function getColumns( $table ) - { - $table = $this->esc( $table, TRUE ); - - $columnsRaw = $this->adapter->get( "PRAGMA table_info('$table')" ); - - $columns = array(); - foreach ( $columnsRaw as $r ) $columns[$r['name']] = $r['type']; - - return $columns; - } - - /** - * @see QueryWriter::addUniqueIndex - */ - public function addUniqueConstraint( $type, $properties ) - { - $tableNoQ = $this->esc( $type, TRUE ); - $name = 'UQ_' . $this->esc( $type, TRUE ) . implode( '__', $properties ); - $t = $this->getTable( $type ); - $t['indexes'][$name] = array( 'name' => $name ); - try { - $this->putTable( $t ); - } catch( SQLException $e ) { - return FALSE; - } - return TRUE; - } - - /** - * @see QueryWriter::sqlStateIn - */ - public function sqlStateIn( $state, $list, $extraDriverDetails = array() ) - { - $stateMap = array( - '23000' => QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION - ); - if ( $state == 'HY000' - && isset($extraDriverDetails[1]) - && $extraDriverDetails[1] == 1 - && ( in_array( QueryWriter::C_SQLSTATE_NO_SUCH_TABLE, $list ) - || in_array( QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, $list ) - )) { - return TRUE; - } - return in_array( ( isset( $stateMap[$state] ) ? $stateMap[$state] : '0' ), $list ); - } - - /** - * Sets an SQL snippet to be used for the next queryRecord() operation. - * SQLite has no SELECT-FOR-UPDATE and filters this. - * - * @param string $sql SQL snippet to use in SELECT statement. - * - * return self - */ - public function setSQLSelectSnippet( $sqlSelectSnippet = '' ) { - if ( $sqlSelectSnippet === AQueryWriter::C_SELECT_SNIPPET_FOR_UPDATE) $sqlSelectSnippet = ''; - $this->sqlSelectSnippet = $sqlSelectSnippet; - return $this; - } - - /** - * @see QueryWriter::addIndex - */ - public function addIndex( $type, $name, $column ) - { - $columns = $this->getColumns( $type ); - if ( !isset( $columns[$column] ) ) return FALSE; - - $table = $this->esc( $type ); - $name = preg_replace( '/\W/', '', $name ); - $column = $this->esc( $column, TRUE ); - - try { - $t = $this->getTable( $type ); - $t['indexes'][$name] = array( 'name' => $column ); - $this->putTable( $t ); - return TRUE; - } catch( SQLException $exception ) { - return FALSE; - } - } - - /** - * @see QueryWriter::wipe - */ - public function wipe( $type ) - { - $table = $this->esc( $type ); - - $this->adapter->exec( "DELETE FROM $table " ); - } - - /** - * @see QueryWriter::addFK - */ - public function addFK( $type, $targetType, $property, $targetProperty, $isDep = FALSE ) - { - return $this->buildFK( $type, $targetType, $property, $targetProperty, $isDep ); - } - - /** - * @see QueryWriter::wipeAll - */ - public function wipeAll() - { - if (AQueryWriter::$noNuke) throw new \Exception('The nuke() command has been disabled using noNuke() or R::feature(novice/...).'); - $this->adapter->exec( 'PRAGMA foreign_keys = 0 ' ); - - foreach ( $this->getTables() as $t ) { - try { $this->adapter->exec( "DROP TABLE IF EXISTS `$t`" ); } catch ( SQLException $e ) { ; } - try { $this->adapter->exec( "DROP TABLE IF EXISTS `$t`" ); } catch ( SQLException $e ) { ; } - } - - $this->adapter->exec( 'PRAGMA foreign_keys = 1 ' ); - } -} -} - -namespace RedBeanPHP\QueryWriter { - -use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter; -use RedBeanPHP\QueryWriter as QueryWriter; -use RedBeanPHP\Adapter\DBAdapter as DBAdapter; -use RedBeanPHP\Adapter as Adapter; -use RedBeanPHP\RedException\SQL as SQLException; - -/** - * RedBeanPHP PostgreSQL Query Writer. - * This is a QueryWriter class for RedBeanPHP. - * This QueryWriter provides support for the PostgreSQL database platform. - * - * @file RedBeanPHP/QueryWriter/PostgreSQL.php - * @author Gabor de Mooij and the RedBeanPHP Community - * @license BSD/GPLv2 - * - * @copyright - * (c) copyright G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community. - * This source file is subject to the BSD/GPLv2 License that is bundled - * with this source code in the file license.txt. - */ -class PostgreSQL extends AQueryWriter implements QueryWriter -{ - /** - * Data types - */ - const C_DATATYPE_INTEGER = 0; - const C_DATATYPE_DOUBLE = 1; - const C_DATATYPE_TEXT = 3; - const C_DATATYPE_SPECIAL_DATE = 80; - const C_DATATYPE_SPECIAL_DATETIME = 81; - const C_DATATYPE_SPECIAL_TIME = 82; //TIME (no zone) only manual - const C_DATATYPE_SPECIAL_TIMEZ = 83; //TIME (plus zone) only manual - const C_DATATYPE_SPECIAL_POINT = 90; - const C_DATATYPE_SPECIAL_LSEG = 91; - const C_DATATYPE_SPECIAL_CIRCLE = 92; - const C_DATATYPE_SPECIAL_MONEY = 93; - const C_DATATYPE_SPECIAL_POLYGON = 94; - const C_DATATYPE_SPECIAL_MONEY2 = 95; //Numbers only money, i.e. fixed point numeric - const C_DATATYPE_SPECIAL_JSON = 96; //JSON support (only manual) - const C_DATATYPE_SPECIFIED = 99; - - /** - * @var DBAdapter - */ - protected $adapter; - - /** - * @var string - */ - protected $quoteCharacter = '"'; - - /** - * @var string - */ - protected $defaultValue = 'DEFAULT'; - - /** - * @var array - */ - protected $DDLTemplates = array( - 'addColumn' => array( - '*' => 'ALTER TABLE %s ADD %s %s ' - ), - 'createTable' => array( - '*' => 'CREATE TABLE %s (id SERIAL PRIMARY KEY) ' - ), - 'widenColumn' => array( - '*' => 'ALTER TABLE %s ALTER COLUMN %s TYPE %s' - ) - ); - - /** - * Returns the insert suffix SQL Snippet - * - * @param string $table table - * - * @return string $sql SQL Snippet - */ - protected function getInsertSuffix( $table ) - { - return 'RETURNING id '; - } - - /** - * @see AQueryWriter::getKeyMapForType - */ - protected function getKeyMapForType( $type ) - { - $table = $this->esc( $type, TRUE ); - $keys = $this->adapter->get( ' - SELECT - information_schema.key_column_usage.constraint_name AS "name", - information_schema.key_column_usage.column_name AS "from", - information_schema.constraint_table_usage.table_name AS "table", - information_schema.constraint_column_usage.column_name AS "to", - information_schema.referential_constraints.update_rule AS "on_update", - information_schema.referential_constraints.delete_rule AS "on_delete" - FROM information_schema.key_column_usage - INNER JOIN information_schema.constraint_table_usage - ON ( - information_schema.key_column_usage.constraint_name = information_schema.constraint_table_usage.constraint_name - AND information_schema.key_column_usage.constraint_schema = information_schema.constraint_table_usage.constraint_schema - AND information_schema.key_column_usage.constraint_catalog = information_schema.constraint_table_usage.constraint_catalog - ) - INNER JOIN information_schema.constraint_column_usage - ON ( - information_schema.key_column_usage.constraint_name = information_schema.constraint_column_usage.constraint_name - AND information_schema.key_column_usage.constraint_schema = information_schema.constraint_column_usage.constraint_schema - AND information_schema.key_column_usage.constraint_catalog = information_schema.constraint_column_usage.constraint_catalog - ) - INNER JOIN information_schema.referential_constraints - ON ( - information_schema.key_column_usage.constraint_name = information_schema.referential_constraints.constraint_name - AND information_schema.key_column_usage.constraint_schema = information_schema.referential_constraints.constraint_schema - AND information_schema.key_column_usage.constraint_catalog = information_schema.referential_constraints.constraint_catalog - ) - WHERE - information_schema.key_column_usage.table_catalog = current_database() - AND information_schema.key_column_usage.table_schema = ANY( current_schemas( FALSE ) ) - AND information_schema.key_column_usage.table_name = ? - ', array( $type ) ); - $keyInfoList = array(); - foreach ( $keys as $k ) { - $label = $this->makeFKLabel( $k['from'], $k['table'], $k['to'] ); - $keyInfoList[$label] = array( - 'name' => $k['name'], - 'from' => $k['from'], - 'table' => $k['table'], - 'to' => $k['to'], - 'on_update' => $k['on_update'], - 'on_delete' => $k['on_delete'] - ); - } - return $keyInfoList; - } - - /** - * Constructor - * Most of the time, you do not need to use this constructor, - * since the facade takes care of constructing and wiring the - * RedBeanPHP core objects. However if you would like to - * assemble an OODB instance yourself, this is how it works: - * - * Usage: - * - * - * $database = new RPDO( $dsn, $user, $pass ); - * $adapter = new DBAdapter( $database ); - * $writer = new PostgresWriter( $adapter ); - * $oodb = new OODB( $writer, FALSE ); - * $bean = $oodb->dispense( 'bean' ); - * $bean->name = 'coffeeBean'; - * $id = $oodb->store( $bean ); - * $bean = $oodb->load( 'bean', $id ); - * - * - * The example above creates the 3 RedBeanPHP core objects: - * the Adapter, the Query Writer and the OODB instance and - * wires them together. The example also demonstrates some of - * the methods that can be used with OODB, as you see, they - * closely resemble their facade counterparts. - * - * The wiring process: create an RPDO instance using your database - * connection parameters. Create a database adapter from the RPDO - * object and pass that to the constructor of the writer. Next, - * create an OODB instance from the writer. Now you have an OODB - * object. - * - * @param Adapter $adapter Database Adapter - */ - public function __construct( Adapter $adapter ) - { - $this->typeno_sqltype = array( - self::C_DATATYPE_INTEGER => ' integer ', - self::C_DATATYPE_DOUBLE => ' double precision ', - self::C_DATATYPE_TEXT => ' text ', - self::C_DATATYPE_SPECIAL_DATE => ' date ', - self::C_DATATYPE_SPECIAL_TIME => ' time ', - self::C_DATATYPE_SPECIAL_TIMEZ => ' time with time zone ', - self::C_DATATYPE_SPECIAL_DATETIME => ' timestamp without time zone ', - self::C_DATATYPE_SPECIAL_POINT => ' point ', - self::C_DATATYPE_SPECIAL_LSEG => ' lseg ', - self::C_DATATYPE_SPECIAL_CIRCLE => ' circle ', - self::C_DATATYPE_SPECIAL_MONEY => ' money ', - self::C_DATATYPE_SPECIAL_MONEY2 => ' numeric(10,2) ', - self::C_DATATYPE_SPECIAL_POLYGON => ' polygon ', - self::C_DATATYPE_SPECIAL_JSON => ' json ', - ); - - $this->sqltype_typeno = array(); - - foreach ( $this->typeno_sqltype as $k => $v ) { - $this->sqltype_typeno[trim( strtolower( $v ) )] = $k; - } - - $this->adapter = $adapter; - } - - /** - * This method returns the datatype to be used for primary key IDS and - * foreign keys. Returns one if the data type constants. - * - * @return integer - */ - public function getTypeForID() - { - return self::C_DATATYPE_INTEGER; - } - - /** - * @see QueryWriter::getTables - */ - public function getTables() - { - return $this->adapter->getCol( 'SELECT table_name FROM information_schema.tables WHERE table_schema = ANY( current_schemas( FALSE ) )' ); - } - - /** - * @see QueryWriter::createTable - */ - public function createTable( $type ) - { - $table = $this->esc( $type ); - - $this->adapter->exec( sprintf( $this->getDDLTemplate( 'createTable', $type ), $table ) ); - } - - /** - * @see QueryWriter::getColumns - */ - public function getColumns( $table ) - { - $table = $this->esc( $table, TRUE ); - - $columnsRaw = $this->adapter->get( "SELECT column_name, data_type FROM information_schema.columns WHERE table_name='$table' AND table_schema = ANY( current_schemas( FALSE ) )" ); - - $columns = array(); - foreach ( $columnsRaw as $r ) { - $columns[$r['column_name']] = $r['data_type']; - } - - return $columns; - } - - /** - * @see QueryWriter::scanType - */ - public function scanType( $value, $flagSpecial = FALSE ) - { - $this->svalue = $value; - - if ( $value === INF ) return self::C_DATATYPE_TEXT; - - if ( $flagSpecial && $value ) { - if ( preg_match( '/^\d{4}\-\d\d-\d\d$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_DATE; - } - - if ( preg_match( '/^\d{4}\-\d\d-\d\d\s\d\d:\d\d:\d\d(\.\d{1,6})?$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_DATETIME; - } - - if ( preg_match( '/^\([\d\.]+,[\d\.]+\)$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_POINT; - } - - if ( preg_match( '/^\[\([\d\.]+,[\d\.]+\),\([\d\.]+,[\d\.]+\)\]$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_LSEG; - } - - if ( preg_match( '/^\<\([\d\.]+,[\d\.]+\),[\d\.]+\>$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_CIRCLE; - } - - if ( preg_match( '/^\((\([\d\.]+,[\d\.]+\),?)+\)$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_POLYGON; - } - - if ( preg_match( '/^\-?(\$|€|¥|£)[\d,\.]+$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_MONEY; - } - - if ( preg_match( '/^-?\d+\.\d{2}$/', $value ) ) { - return PostgreSQL::C_DATATYPE_SPECIAL_MONEY2; - } - if ( self::$flagUseJSONColumns && $this->isJSON( $value ) ) { - return self::C_DATATYPE_SPECIAL_JSON; - } - } - - if ( is_float( $value ) ) return self::C_DATATYPE_DOUBLE; - - if ( $this->startsWithZeros( $value ) ) return self::C_DATATYPE_TEXT; - - if ( $value === FALSE || $value === TRUE || $value === NULL || ( is_numeric( $value ) - && AQueryWriter::canBeTreatedAsInt( $value ) - && $value < 2147483648 - && $value > -2147483648 ) - ) { - return self::C_DATATYPE_INTEGER; - } elseif ( is_numeric( $value ) ) { - return self::C_DATATYPE_DOUBLE; - } else { - return self::C_DATATYPE_TEXT; - } - } - - /** - * @see QueryWriter::code - */ - public function code( $typedescription, $includeSpecials = FALSE ) - { - $r = ( isset( $this->sqltype_typeno[$typedescription] ) ) ? $this->sqltype_typeno[$typedescription] : 99; - - if ( $includeSpecials ) return $r; - - if ( $r >= QueryWriter::C_DATATYPE_RANGE_SPECIAL ) { - return self::C_DATATYPE_SPECIFIED; - } - - return $r; - } - - /** - * @see QueryWriter::widenColumn - */ - public function widenColumn( $beanType, $column, $datatype ) - { - $table = $beanType; - $type = $datatype; - - $table = $this->esc( $table ); - $column = $this->esc( $column ); - - $newtype = $this->typeno_sqltype[$type]; - - $this->adapter->exec( sprintf( $this->getDDLTemplate( 'widenColumn', $beanType, $column ), $table, $column, $newtype ) ); - - } - - /** - * @see QueryWriter::addUniqueIndex - */ - public function addUniqueConstraint( $type, $properties ) - { - $tableNoQ = $this->esc( $type, TRUE ); - $columns = array(); - foreach( $properties as $key => $column ) $columns[$key] = $this->esc( $column ); - $table = $this->esc( $type ); - sort( $columns ); //else we get multiple indexes due to order-effects - $name = "UQ_" . sha1( $table . implode( ',', $columns ) ); - $sql = "ALTER TABLE {$table} - ADD CONSTRAINT $name UNIQUE (" . implode( ',', $columns ) . ")"; - try { - $this->adapter->exec( $sql ); - } catch( SQLException $e ) { - return FALSE; - } - return TRUE; - } - - /** - * @see QueryWriter::sqlStateIn - */ - public function sqlStateIn( $state, $list, $extraDriverDetails = array() ) - { - $stateMap = array( - '42P01' => QueryWriter::C_SQLSTATE_NO_SUCH_TABLE, - '42703' => QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, - '23505' => QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION, - '55P03' => QueryWriter::C_SQLSTATE_LOCK_TIMEOUT - ); - return in_array( ( isset( $stateMap[$state] ) ? $stateMap[$state] : '0' ), $list ); - } - - /** - * @see QueryWriter::addIndex - */ - public function addIndex( $type, $name, $property ) - { - $table = $this->esc( $type ); - $name = preg_replace( '/\W/', '', $name ); - $column = $this->esc( $property ); - - try { - $this->adapter->exec( "CREATE INDEX {$name} ON $table ({$column}) " ); - return TRUE; - } catch ( SQLException $e ) { - return FALSE; - } - } - - /** - * @see QueryWriter::addFK - */ - public function addFK( $type, $targetType, $property, $targetProperty, $isDep = FALSE ) - { - $table = $this->esc( $type ); - $targetTable = $this->esc( $targetType ); - $field = $this->esc( $property ); - $targetField = $this->esc( $targetProperty ); - $tableNoQ = $this->esc( $type, TRUE ); - $fieldNoQ = $this->esc( $property, TRUE ); - if ( !is_null( $this->getForeignKeyForTypeProperty( $tableNoQ, $fieldNoQ ) ) ) return FALSE; - try{ - $delRule = ( $isDep ? 'CASCADE' : 'SET NULL' ); - $this->adapter->exec( "ALTER TABLE {$table} - ADD FOREIGN KEY ( {$field} ) REFERENCES {$targetTable} - ({$targetField}) ON DELETE {$delRule} ON UPDATE {$delRule} DEFERRABLE ;" ); - return TRUE; - } catch ( SQLException $e ) { - return FALSE; - } - } - - /** - * @see QueryWriter::wipeAll - */ - public function wipeAll() - { - if (AQueryWriter::$noNuke) throw new \Exception('The nuke() command has been disabled using noNuke() or R::feature(novice/...).'); - $this->adapter->exec( 'SET CONSTRAINTS ALL DEFERRED' ); - - foreach ( $this->getTables() as $t ) { - $t = $this->esc( $t ); - //Some plugins (PostGIS have unremovable tables/views), avoid exceptions. - try { $this->adapter->exec( "DROP TABLE IF EXISTS $t CASCADE " ); }catch( \Exception $e ) {} - } - - $this->adapter->exec( 'SET CONSTRAINTS ALL IMMEDIATE' ); - } -} -} - namespace RedBeanPHP\QueryWriter { use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter; use RedBeanPHP\QueryWriter as QueryWriter; @@ -8580,8 +7765,6 @@ class CUBRID extends AQueryWriter implements QueryWriter */ public function scanType( $value, $flagSpecial = FALSE ) { - $this->svalue = $value; - if ( is_null( $value ) ) { return self::C_DATATYPE_INTEGER; } @@ -8784,6 +7967,8 @@ class SQL extends RedException /** * @param array $driverDetails + * + * @return void */ public function setDriverDetails($driverDetails) { @@ -8840,7 +8025,7 @@ use RedBeanPHP\Cursor\NullCursor as NullCursor; * Abstract Repository. * * OODB manages two repositories, a fluid one that - * adjust the database schema on-the-fly to accomodate for + * adjust the database schema on-the-fly to accommodate for * new bean types (tables) and new properties (columns) and * a frozen one for use in a production environment. OODB * allows you to swap the repository instances using the freeze() @@ -8862,21 +8047,26 @@ abstract class Repository */ protected $stash = NULL; - /* + /** * @var integer */ protected $nesting = 0; /** - * @var DBAdapter + * @var QueryWriter */ protected $writer; /** - * @var boolean + * @var boolean|array */ protected $partialBeans = FALSE; + /** + * @var OODB + */ + public $oodb = NULL; + /** * Toggles 'partial bean mode'. If this mode has been * selected the repository will only update the fields of a bean that @@ -8889,7 +8079,7 @@ abstract class Repository * * @param boolean|array $yesNoBeans List of type names or 'all' * - * @return mixed + * @return boolean|array */ public function usePartialBeans( $yesNoBeans ) { @@ -8904,12 +8094,12 @@ abstract class Repository * addition, deleted 'trash can' or residue. Next, the different groups * of beans will be processed accordingly and the reference bean (i.e. * the one that was passed to the method as an argument) will be stored. - * Each type of list (own/shared) has 3 bean processors: + * Each type of list (own/shared) has 3 bean processors: * * - trashCanProcessor : removes the bean or breaks its association with the current bean * - additionProcessor : associates the bean with the current one * - residueProcessor : manages beans in lists that 'remain' but may need to be updated - * + * * This method first groups the beans and then calls the * internal processing methods. * @@ -8982,7 +8172,7 @@ abstract class Repository * A bean may contain lists. This * method handles shared addition lists; i.e. * the $bean->sharedObject properties. - * Shared beans will be associated with eachother using the + * Shared beans will be associated with each other using the * Association Manager. * * @param OODBBean $bean the bean @@ -9218,7 +8408,7 @@ abstract class Repository * @param int $number number of beans you would like to get * @param boolean $alwaysReturnArray if TRUE always returns the result as an array * - * @return OODBBean + * @return OODBBean|OODBBean[] */ public function dispense( $type, $number = 1, $alwaysReturnArray = FALSE ) { @@ -9398,7 +8588,7 @@ abstract class Repository * New in 4.3.2: meta mask. The meta mask is a special mask to send * data from raw result rows to the meta store of the bean. This is * useful for bundling additional information with custom queries. - * Values of every column whos name starts with $mask will be + * Values of every column who's name starts with $mask will be * transferred to the meta section of the bean under key 'data.bundle'. * * @param string $type type of beans you would like to have @@ -9477,10 +8667,6 @@ abstract class Repository public function count( $type, $addSQL = '', $bindings = array() ) { $type = AQueryWriter::camelsSnake( $type ); - if ( count( explode( '_', $type ) ) > 2 ) { - throw new RedException( 'Invalid type for count.' ); - } - try { $count = (int) $this->writer->queryRecordCount( $type, array(), $addSQL, $bindings ); } catch ( SQLException $exception ) { @@ -9497,7 +8683,7 @@ abstract class Repository * * @param OODBBean|SimpleModel $bean bean you want to remove from database * - * @return void + * @return int */ public function trash( $bean ) { @@ -9515,7 +8701,7 @@ abstract class Repository } } try { - $deleted = $this->writer->deleteRecord( $bean->getMeta( 'type' ), array( 'id' => array( $bean->id ) ), NULL ); + $deleted = $this->writer->deleteRecord( $bean->getMeta( 'type' ), array( 'id' => array( $bean->id ) ) ); } catch ( SQLException $exception ) { $this->handleException( $exception ); } @@ -9528,8 +8714,6 @@ abstract class Repository * Checks whether the specified table already exists in the database. * Not part of the Object Database interface! * - * @deprecated Use AQueryWriter::typeExists() instead. - * * @param string $table table name * * @return boolean @@ -9579,7 +8763,7 @@ use RedBeanPHP\Repository as Repository; /** * Fluid Repository. * OODB manages two repositories, a fluid one that - * adjust the database schema on-the-fly to accomodate for + * adjust the database schema on-the-fly to accommodate for * new bean types (tables) and new properties (columns) and * a frozen one for use in a production environment. OODB * allows you to swap the repository instances using the freeze() @@ -9654,9 +8838,10 @@ class Fluid extends Repository * * This method will also apply indexes, unique constraints and foreign keys. * - * @param OODBBean $bean bean to get cast data from and store meta in - * @param string $property property to store - * @param mixed $value value to store + * @param OODBBean $bean bean to get cast data from and store meta in + * @param string $property property to store + * @param mixed $value value to store + * @param array|NULL &$columns * * @return void */ @@ -9902,7 +9087,7 @@ use RedBeanPHP\Repository as Repository; /** * Frozen Repository. * OODB manages two repositories, a fluid one that - * adjust the database schema on-the-fly to accomodate for + * adjust the database schema on-the-fly to accommodate for * new bean types (tables) and new properties (columns) and * a frozen one for use in a production environment. OODB * allows you to swap the repository instances using the freeze() @@ -10116,7 +9301,7 @@ class OODB extends Observable protected $nesting = 0; /** - * @var DBAdapter + * @var QueryWriter */ protected $writer; @@ -10126,12 +9311,12 @@ class OODB extends Observable protected $isFrozen = FALSE; /** - * @var FacadeBeanHelper + * @var BeanHelper|NULL */ protected $beanhelper = NULL; /** - * @var AssociationManager + * @var AssociationManager|NULL */ protected $assocManager = NULL; @@ -10141,12 +9326,12 @@ class OODB extends Observable protected $repository = NULL; /** - * @var FrozenRepo + * @var FrozenRepo|NULL */ protected $frozenRepository = NULL; /** - * @var FluidRepo + * @var FluidRepo|NULL */ protected $fluidRepository = NULL; @@ -10172,7 +9357,7 @@ class OODB extends Observable * Unboxes a bean from a FUSE model if needed and checks whether the bean is * an instance of OODBBean. * - * @param OODBBean $bean bean you wish to unbox + * @param OODBBean|SimpleModel $bean bean you wish to unbox * * @return OODBBean */ @@ -10234,11 +9419,11 @@ class OODB extends Observable /** * Toggles fluid or frozen mode. In fluid mode the database - * structure is adjusted to accomodate your objects. In frozen mode + * structure is adjusted to accommodate your objects. In frozen mode * this is not the case. * * You can also pass an array containing a selection of frozen types. - * Let's call this chilly mode, it's just like fluid mode except that + * Let's call this chill mode, it's just like fluid mode except that * certain types (i.e. tables) aren't touched. * * @param boolean|array $toggle TRUE if you want to use OODB instance in frozen mode @@ -10278,7 +9463,7 @@ class OODB extends Observable /** * Returns the current mode of operation of RedBean. * In fluid mode the database - * structure is adjusted to accomodate your objects. + * structure is adjusted to accommodate your objects. * In frozen mode * this is not the case. * @@ -10318,7 +9503,7 @@ class OODB extends Observable * @param string $number number of beans you would like to get * @param boolean $alwaysReturnArray if TRUE always returns the result as an array * - * @return OODBBean + * @return OODBBean|OODBBean[] */ public function dispense( $type, $number = 1, $alwaysReturnArray = FALSE ) { @@ -10347,7 +9532,7 @@ class OODB extends Observable * Returns the current bean helper. * Bean helpers assist beans in getting a reference to a toolbox. * - * @return BeanHelper + * @return BeanHelper|NULL */ public function getBeanHelper() { @@ -10369,7 +9554,7 @@ class OODB extends Observable } /** - * Searches the database for a bean that matches conditions $conditions and sql $addSQL + * Searches the database for a bean that matches conditions $conditions and sql $sql * and returns an array containing all the beans that have been found. * * Conditions need to take form: @@ -10387,10 +9572,10 @@ class OODB extends Observable * Note that you can use property names; the columns will be extracted using the * appropriate bean formatter. * - * @param string $type type of beans you are looking for - * @param array $conditions list of conditions - * @param string $sql SQL to be used in query - * @param array $bindings a list of values to bind to query parameters + * @param string $type type of beans you are looking for + * @param array $conditions list of conditions + * @param string|NULL $sql SQL to be used in query + * @param array $bindings a list of values to bind to query parameters * * @return array */ @@ -10402,9 +9587,9 @@ class OODB extends Observable /** * Same as find() but returns a BeanCollection. * - * @param string $type type of beans you are looking for - * @param string $sql SQL to be used in query - * @param array $bindings a list of values to bind to query parameters + * @param string $type type of beans you are looking for + * @param string|NULL $sql SQL to be used in query + * @param array $bindings a list of values to bind to query parameters * * @return BeanCollection */ @@ -10415,9 +9600,6 @@ class OODB extends Observable /** * Checks whether the specified table already exists in the database. - * Not part of the Object Database interface! - * - * @deprecated Use AQueryWriter::typeExists() instead. * * @param string $table table name * @@ -10492,7 +9674,7 @@ class OODB extends Observable * * @param OODBBean|SimpleModel $bean bean you want to remove from database * - * @return void + * @return int */ public function trash( $bean ) { @@ -10623,10 +9805,10 @@ class OODB extends Observable * MySQL spatial columns, because they need to be processed first using * the asText/GeomFromText functions. * - * @param string $mode mode to set function for, i.e. read or write - * @param string $field field (table.column) to bind SQL function to - * @param string $function SQL function to bind to field - * @param boolean $isTemplate TRUE if $function is an SQL string, FALSE for just a function name + * @param string $mode mode to set function for, i.e. read or write + * @param string $field field (table.column) to bind SQL function to + * @param string|NULL $function SQL function to bind to field + * @param boolean $isTemplate TRUE if $function is an SQL string, FALSE for just a function name * * @return void */ @@ -10982,7 +10164,7 @@ class Finder * R::genSlots( $users, * 'SELECT country.* FROM country WHERE id IN ( %s )' ), * array_column( $users, 'country_id' ), - * [Finder::onmap('country', $gebruikers)] + * [Finder::onmap('country', $users)] * ); * * @@ -11011,9 +10193,9 @@ class Finder * array parameter; you can either use the question mark notation * or the slot-notation (:keyname). * - * @param string $type type the type of bean you are looking for - * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type type the type of bean you are looking for + * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return array */ @@ -11037,9 +10219,9 @@ class Finder * * @see Finder::find * - * @param string $type type the type of bean you are looking for - * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type type the type of bean you are looking for + * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return array */ @@ -11060,9 +10242,9 @@ class Finder * * @see Finder::find * - * @param string $type type the type of bean you are looking for - * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type type the type of bean you are looking for + * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return OODBBean|NULL */ @@ -11086,9 +10268,9 @@ class Finder * * @see Finder::find * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return OODBBean|NULL */ @@ -11110,9 +10292,9 @@ class Finder * * @see Finder::find * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return array */ @@ -11380,7 +10562,7 @@ class Finder } else { list($field1, $field2) = $matcher; foreach( $beans[$b] as $key => $bean ) { - $beans[$b][$key]->{$field1} = $beans[$a][$bean->{$field2}]; + $beans[$b][$key]->{$field1} = (isset($beans[$a][$bean->{$field2}]) ? $beans[$a][$bean->{$field2}] : NULL); } } } @@ -11429,6 +10611,11 @@ class AssociationManager extends Observable */ protected $writer; + /** + * @var ToolBox + */ + public $toolbox; + /** * Exception handler. * Fluid and Frozen mode have different ways of handling @@ -11607,7 +10794,7 @@ class AssociationManager extends Observable * * @param OODBBean|array $bean a bean object or an array of beans * @param string $type type of bean you're interested in - * @param string $sql SQL snippet (optional) + * @param string|NULL $sql SQL snippet (optional) * @param array $bindings bindings for your SQL string * * @return integer @@ -11726,7 +10913,7 @@ class AssociationManager extends Observable * Since 3.2, you can now also pass an array of beans instead just one * bean as the first parameter. * - * @param OODBBean|array $bean the bean you have + * @param OODBBean $bean the bean you have * @param string $type the type of beans you want * @param string $sql SQL snippet for extra filtering * @param array $bindings values to be inserted in SQL slots @@ -11764,7 +10951,7 @@ use RedBeanPHP\OODBBean as OODBBean; * Interface for Bean Helper. * A little bolt that glues the whole machinery together. * The Bean Helper is passed to the OODB RedBeanPHP Object to - * faciliatte the creation of beans and providing them with + * facilitate the creation of beans and providing them with * a toolbox. The Helper also facilitates the FUSE feature, * determining how beans relate to their models. By overriding * the getModelForBean method you can tune the FUSEing to @@ -11841,7 +11028,7 @@ class SimpleFacadeBeanHelper implements BeanHelper /** * Factory function to create instance of Simple Model, if any. * - * @var \Closure + * @var callable|NULL */ private static $factory = null; @@ -11863,7 +11050,7 @@ class SimpleFacadeBeanHelper implements BeanHelper * Sets the factory function to create the model when using FUSE * to connect a bean to a model. * - * @param \Closure $factory factory function + * @param callable|NULL $factory factory function * * @return void */ @@ -11888,6 +11075,28 @@ class SimpleFacadeBeanHelper implements BeanHelper $model = $bean->getMeta( 'type' ); $prefix = defined( 'REDBEAN_MODEL_PREFIX' ) ? REDBEAN_MODEL_PREFIX : '\\Model_'; + return $this->resolveModel($prefix, $model, $bean); + } + + /** + * Resolves the model associated with the bean using the model name (type), + * the prefix and the bean. + * + * @note + * If REDBEAN_CLASS_AUTOLOAD is defined this will be passed to class_exist as + * autoloading flag. + * + * @param string $prefix Prefix to use for resolution + * @param string $model Type name + * @param OODBBean $bean Bean to resolve model for + * + * @return SimpleModel|CustomModel|NULL + */ + protected function resolveModel($prefix, $model, $bean) { + + /* Determine autoloading preference */ + $autoloadFlag = ( defined( 'REDBEAN_CLASS_AUTOLOAD' ) ? REDBEAN_CLASS_AUTOLOAD : TRUE ); + if ( strpos( $model, '_' ) !== FALSE ) { $modelParts = explode( '_', $model ); $modelName = ''; @@ -11897,13 +11106,13 @@ class SimpleFacadeBeanHelper implements BeanHelper $modelName = $prefix . $modelName; if ( !class_exists( $modelName ) ) { $modelName = $prefix . ucfirst( $model ); - if ( !class_exists( $modelName ) ) { + if ( !class_exists( $modelName, $autoloadFlag ) ) { return NULL; } } } else { $modelName = $prefix . ucfirst( $model ); - if ( !class_exists( $modelName ) ) { + if ( !class_exists( $modelName, $autoloadFlag ) ) { return NULL; } } @@ -11922,6 +11131,63 @@ class SimpleFacadeBeanHelper implements BeanHelper } } +namespace RedBeanPHP\BeanHelper { + +use RedBeanPHP\BeanHelper as BeanHelper; +use RedBeanPHP\Facade as Facade; +use RedBeanPHP\OODBBean as OODBBean; +use RedBeanPHP\SimpleModelHelper as SimpleModelHelper; +use RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper as SimpleFacadeBeanHelper; + +/** + * Dynamic Bean Helper. + * + * The dynamic bean helper allows you to use differently namespaced + * classes for models per database connection. + * + * @file RedBeanPHP/BeanHelper/DynamicBeanHelper.php + * @author Gabor de Mooij and the RedBeanPHP Community + * @license BSD/GPLv2 + * + * @copyright + * (c) copyright G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community + * This source file is subject to the BSD/GPLv2 License that is bundled + * with this source code in the file license.txt. + */ +class DynamicBeanHelper extends SimpleFacadeBeanHelper implements BeanHelper +{ + /** + * Model prefix to be used for the current database connection. + * + * @var string + */ + private $modelPrefix; + + /** + * Constructor + * + * Usage: + * + * + * R::addDatabase( ..., new DynamicBeanHelper('Prefix1_') ); + * + * + * @param string $modelPrefix prefix + */ + public function __construct( $modelPrefix ) { + $this->modelPrefix = $modelPrefix; + } + + /** + * @see BeanHelper::getModelForBean + */ + public function getModelForBean( OODBBean $bean ) + { + return $this->resolveModel( $this->modelPrefix, $bean->getMeta( 'type' ), $bean ); + } +} +} + namespace RedBeanPHP { use RedBeanPHP\OODBBean as OODBBean; @@ -12079,7 +11345,7 @@ class SimpleModelHelper implements Observer * invoke the corresponding method on the bean. * * @param string $eventName i.e. 'delete', 'after_delete' - * @param OODBean $bean affected bean + * @param OODBBean $bean affected bean * * @return void */ @@ -12157,7 +11423,7 @@ class TagManager protected $associationManager; /** - * @var OODBBean + * @var OODB */ protected $redbean; @@ -12166,7 +11432,7 @@ class TagManager * it will split the string into words and return an array instead. * In case of an array the argument will be returned 'as is'. * - * @param array|string $tagList list of tags + * @param array|string|false $tagList list of tags * * @return array */ @@ -12182,12 +11448,12 @@ class TagManager } /** - * Finds a tag bean by it's title. + * Finds a tag bean by its title. * Internal method. * * @param string $title title to search for * - * @return OODBBean + * @return OODBBean|NULL */ protected function findTagByTitle( $title ) { @@ -12218,7 +11484,7 @@ class TagManager } /** - * Tests whether a bean has been associated with one ore more + * Tests whether a bean has been associated with one or more * of the listed tags. If the third parameter is TRUE this method * will return TRUE only if all tags that have been specified are indeed * associated with the given bean, otherwise FALSE. @@ -12276,8 +11542,8 @@ class TagManager * In the example above, the $blog bean will no longer * be associated with the tags 'smart' and 'interesting'. * - * @param OODBBean $bean tagged bean - * @param array $tagList list of tags (names) + * @param OODBBean $bean tagged bean + * @param array|string $tagList list of tags (names) * * @return void */ @@ -12353,8 +11619,8 @@ class TagManager * The example adds the tag 'halloween' to the $blog * bean. * - * @param OODBBean $bean bean to tag - * @param array $tagList list of tags to add to bean + * @param OODBBean $bean bean to tag + * @param array|string|false $tagList list of tags to add to bean * * @return void */ @@ -12701,7 +11967,7 @@ use RedBeanPHP\Util\Feature; * RedBean Facade * * Version Information - * RedBean Version @version 5.6 + * RedBean Version @version 5.7 * * This class hides the object landscape of * RedBeanPHP behind a single letter class providing @@ -12721,7 +11987,7 @@ class Facade /** * RedBeanPHP version constant. */ - const C_REDBEANPHP_VERSION = '5.6'; + const C_REDBEANPHP_VERSION = '5.7'; /** * @var ToolBox @@ -12739,7 +12005,7 @@ class Facade private static $writer; /** - * @var DBAdapter + * @var Adapter */ private static $adapter; @@ -12779,7 +12045,7 @@ class Facade private static $logger; /** - * @var array + * @var callable[] */ private static $plugins = array(); @@ -12789,12 +12055,12 @@ class Facade private static $exportCaseStyle = 'default'; /** - * @var flag allows transactions through facade in fluid mode + * @var bool flag allows transactions through facade in fluid mode */ private static $allowFluidTransactions = FALSE; /** - * @var flag allows to unfreeze if needed with store(all) + * @var bool flag allows to unfreeze if needed with store(all) */ private static $allowHybridMode = FALSE; @@ -12809,7 +12075,7 @@ class Facade public static $currentDB = ''; /** - * @var array + * @var ToolBox[] */ public static $toolboxes = array(); @@ -12821,7 +12087,7 @@ class Facade * @param string $sql the sql you want to execute * @param array $bindings array of values to be bound to query statement * - * @return array + * @return array|int|Cursor|NULL */ private static function query( $method, $sql, $bindings ) { @@ -12856,6 +12122,8 @@ class Facade * flag. * * @param boolean $hybrid + * + * @return bool */ public static function setAllowHybridMode( $hybrid ) { @@ -12933,11 +12201,11 @@ class Facade * a connection is really required, for instance when attempting to load * a bean. * - * @param string $dsn Database connection string - * @param string $username Username for database - * @param string $password Password for database - * @param boolean $frozen TRUE if you want to setup in frozen mode - * @param boolean $partialBeans TRUE to enable partial bean updates + * @param string|\PDO|NULL $dsn Database connection string + * @param string|NULL $username Username for database + * @param string|NULL $password Password for database + * @param boolean|string[] $frozen TRUE if you want to setup in frozen mode + * @param boolean|string[] $partialBeans TRUE to enable partial bean updates * @param array $options Additional (PDO) options to pass * * @return ToolBox @@ -12988,7 +12256,7 @@ class Facade * Toggles fluid transactions. By default fluid transactions * are not active. Starting, committing or rolling back a transaction * through the facade in fluid mode will have no effect. If you wish - * to replace this standard portable behavor with behavior depending + * to replace this standard portable behavior with behavior depending * on how the used database platform handles fluid (DDL) transactions * set this flag to TRUE. * @@ -13051,6 +12319,7 @@ class Facade */ public static function transaction( $callback ) { + if ( !self::$allowFluidTransactions && !self::$redbean->isFrozen() ) return FALSE; return Transaction::transaction( self::$adapter, $callback ); } @@ -13068,28 +12337,35 @@ class Facade * This method allows you to dynamically add (and select) new databases * to the facade. Adding a database with the same key will cause an exception. * - * @param string $key ID for the database - * @param string $dsn DSN for the database - * @param string $user user for connection - * @param NULL|string $pass password for connection - * @param bool $frozen whether this database is frozen or not + * @param string $key ID for the database + * @param string|\PDO $dsn DSN for the database + * @param string|NULL $user user for connection + * @param string|NULL $pass password for connection + * @param bool|string[] $frozen whether this database is frozen or not + * @param bool|string[] $partialBeans should we load partial beans? + * @param array $options additional options for the query writer + * @param BeanHelper|NULL $beanHelper Beanhelper to use (use this for DB specific model prefixes) * * @return void */ - public static function addDatabase( $key, $dsn, $user = NULL, $pass = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array() ) + public static function addDatabase( $key, $dsn, $user = NULL, $pass = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array(), $beanHelper = NULL ) { if ( isset( self::$toolboxes[$key] ) ) { throw new RedException( 'A database has already been specified for this key.' ); } self::$toolboxes[$key] = self::createToolbox($dsn, $user, $pass, $frozen, $partialBeans, $options); + + if ( !is_null( $beanHelper ) ) { + self::$toolboxes[$key]->getRedBean()->setBeanHelper( $beanHelper ); + } } /** * Creates a toolbox. This method can be called if you want to use redbean non-static. - * It has the same interface as R::setup(). The createToolbx() method can be called - * without any arguments, in this case it will try to create a SQLite database in - * /tmp called red.db (this only works on UNIX-like systems). + * It has the same interface as R::setup(). The createToolbox() method can be called + * without any arguments, in this case it will try to create a SQLite database in + * /tmp called red.db (this only works on UNIX-like systems). * * Usage: * @@ -13111,15 +12387,17 @@ class Facade * Instead, it will prepare the connection and connect 'lazily', i.e. the moment * a connection is really required, for instance when attempting to load a bean. * - * @param string $dsn Database connection string + * @param string|\PDO $dsn Database connection string * @param string $username Username for database * @param string $password Password for database - * @param boolean $frozen TRUE if you want to setup in frozen mode + * @param boolean|string[] $frozen TRUE if you want to setup in frozen mode + * @param boolean|string[] $partialBeans TRUE to enable partial bean updates + * @param array $options * * @return ToolBox */ - public static function createToolbox( $dsn = NULL, $username = NULL, $password = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array() ) - { + public static function createToolbox( $dsn, $username = NULL, $password = NULL, $frozen = FALSE, $partialBeans = FALSE, $options = array() ) + { if ( is_object($dsn) ) { $db = new RPDO( $dsn ); $dbType = $db->getDatabaseType(); @@ -13144,6 +12422,7 @@ class Facade throw new RedException( 'Unsupported database ('.$wkey.').' ); } $writerClass = '\\RedBeanPHP\\QueryWriter\\'.$writers[$wkey]; + /** @var AQueryWriter $writer */ $writer = new $writerClass( $adapter ); $redbean = new OODB( $writer, $frozen ); @@ -13179,6 +12458,7 @@ class Facade * switched and FALSE otherwise (for instance if you already using the specified database). * * @param string $key Key of the database to select + * @param bool $force * * @return boolean */ @@ -13208,7 +12488,7 @@ class Facade * There are 2 debug styles: * * Classic: separate parameter bindings, explicit and complete but less readable - * Fancy: interpersed bindings, truncates large strings, highlighted schema changes + * Fancy: interspersed bindings, truncates large strings, highlighted schema changes * * Fancy style is more readable but sometimes incomplete. * @@ -13270,9 +12550,9 @@ class Facade * the column types used to store their values. * If no type is passed, this method returns a list of all tables in the database. * - * @param string $type Type of bean (i.e. table) you want to inspect + * @param string|NULL $type Type of bean (i.e. table) you want to inspect, or NULL for a list of all tables * - * @return array + * @return string[] */ public static function inspect( $type = NULL ) { @@ -13336,14 +12616,16 @@ class Facade /** * Toggles fluid or frozen mode. In fluid mode the database - * structure is adjusted to accomodate your objects. In frozen mode + * structure is adjusted to accommodate your objects. In frozen mode * this is not the case. * * You can also pass an array containing a selection of frozen types. * Let's call this chilly mode, it's just like fluid mode except that * certain types (i.e. tables) aren't touched. * - * @param boolean|array $tf mode of operation (TRUE means frozen) + * @param boolean|string[] $tf mode of operation (TRUE means frozen) + * + * @return void */ public static function freeze( $tf = TRUE ) { @@ -13364,10 +12646,10 @@ class Facade * list( $author, $bio ) = R::loadMulti( 'author, bio', $id ); * * - * @param string|array $types the set of types to load at once - * @param mixed $id the common ID + * @param string|string[] $types the set of types to load at once + * @param int $id the common ID * - * @return OODBBean + * @return OODBBean[] */ public static function loadMulti( $types, $id ) { @@ -13409,7 +12691,7 @@ class Facade * * @param string $type type of bean you want to load * @param integer $id ID of the bean you want to load - * @param string $snippet string to use after select (optional) + * @param string|NULL $snippet string to use after select (optional) * * @return OODBBean */ @@ -13463,10 +12745,10 @@ class Facade * * * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause * @param array $bindings array of values to be bound to parameters in query * - * @return array + * @return OODBBean[] */ public static function findForUpdate( $type, $sql = NULL, $bindings = array() ) { @@ -13478,16 +12760,16 @@ class Facade * Same as findForUpdate but returns just one bean and adds LIMIT-clause. * * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause * @param array $bindings array of values to be bound to parameters in query * - * @return array + * @return OODBBean|NULL */ public static function findOneForUpdate( $type, $sql = NULL, $bindings = array() ) { $sql = self::getWriter()->glueLimitOne( $sql ); $beans = self::findForUpdate($type, $sql, $bindings); - return !empty($beans) ? reset($beans) : NULL; + return empty($beans) ? NULL : reset($beans); } /** @@ -13518,7 +12800,7 @@ class Facade * @param string|OODBBean|SimpleModel $beanOrType bean you want to remove from database * @param integer $id ID if the bean to trash (optional, type-id variant only) * - * @return void + * @return int */ public static function trash( $beanOrType, $id = NULL ) { @@ -13566,11 +12848,11 @@ class Facade * ] ); * * - * @param string|array $typeOrBeanArray type or bean array to import + * @param string|OODBBean[] $typeOrBeanArray type or bean array to import * @param integer $num number of beans to dispense * @param boolean $alwaysReturnArray if TRUE always returns the result as an array * - * @return array|OODBBean + * @return OODBBean|OODBBean[] */ public static function dispense( $typeOrBeanArray, $num = 1, $alwaysReturnArray = FALSE ) { @@ -13611,15 +12893,15 @@ class Facade } /** - * Convience method. Tries to find beans of a certain type, + * Convenience method. Tries to find beans of a certain type, * if no beans are found, it dispenses a bean of that type. * Note that this function always returns an array. * - * @param string $type type of bean you are looking for - * @param string $sql SQL code for finding the bean - * @param array $bindings parameters to bind to SQL + * @param string $type type of bean you are looking for + * @param string|NULL $sql SQL code for finding the bean + * @param array $bindings parameters to bind to SQL * - * @return array + * @return OODBBean[] */ public static function findOrDispense( $type, $sql = NULL, $bindings = array() ) { @@ -13630,9 +12912,9 @@ class Facade /** * Same as findOrDispense but returns just one element. * - * @param string $type type of bean you are looking for - * @param string $sql SQL code for finding the bean - * @param array $bindings parameters to bind to SQL + * @param string $type type of bean you are looking for + * @param string|NULL $sql SQL code for finding the bean + * @param array $bindings parameters to bind to SQL * * @return OODBBean */ @@ -13652,12 +12934,15 @@ class Facade * * Your SQL does not have to start with a WHERE-clause condition. * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings array of values to be bound to parameters in query - * @param string $snippet SQL snippet to include in query (for example: FOR UPDATE) + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings array of values to be bound to parameters in query + * @param string|NULL $snippet SQL snippet to include in query (for example: FOR UPDATE) * - * @return array + * @phpstan-param literal-string|null $sql + * @psalm-param literal-string|null $sql + * + * @return OODBBean[] */ public static function find( $type, $sql = NULL, $bindings = array(), $snippet = NULL ) { @@ -13668,11 +12953,11 @@ class Facade /** * Alias for find(). * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings array of values to be bound to parameters in query + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings array of values to be bound to parameters in query * - * @return array + * @return OODBBean[] */ public static function findAll( $type, $sql = NULL, $bindings = array() ) { @@ -13688,9 +12973,9 @@ class Facade * * @see Finder::find * - * @param string $type type the type of bean you are looking for - * @param string $sql sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type type the type of bean you are looking for + * @param string|NULL $sql sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return array */ @@ -13702,9 +12987,9 @@ class Facade /** * Like R::find() but returns the first bean only. * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings array of values to be bound to parameters in query + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings array of values to be bound to parameters in query * * @return OODBBean|NULL */ @@ -13727,9 +13012,9 @@ class Facade * * @see Finder::find * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return OODBBean|NULL */ @@ -13744,9 +13029,9 @@ class Facade * cursors - this is useful for processing large datasets. A bean collection * will not load all beans into memory all at once, just one at a time. * - * @param string $type the type of bean you are looking for - * @param string $sql SQL query to find the desired bean, starting right after WHERE clause - * @param array $bindings values array of values to be bound to parameters in query + * @param string $type the type of bean you are looking for + * @param string|NULL $sql SQL query to find the desired bean, starting right after WHERE clause + * @param array $bindings values array of values to be bound to parameters in query * * @return BeanCollection */ @@ -13816,10 +13101,10 @@ class Facade * * @note instead of an SQL query you can pass a result array as well. * - * @param string|array $types a list of types (either array or comma separated string) - * @param string|array $sql an SQL query or an array of prefetched records - * @param array $bindings optional, bindings for SQL query - * @param array $remappings optional, an array of remapping arrays + * @param string|string[] $types a list of types (either array or comma separated string) + * @param string|array[]|NULL $sql an SQL query or an array of prefetched records + * @param array $bindings optional, bindings for SQL query + * @param array[] $remappings optional, an array of remapping arrays * * @return array */ @@ -13838,9 +13123,9 @@ class Facade * passed IDs as their keys. * * @param string $type type of beans - * @param array $ids ids to load + * @param int[] $ids ids to load * - * @return array + * @return OODBBean[] */ public static function batch( $type, $ids ) { @@ -13854,9 +13139,9 @@ class Facade * loadAll. * * @param string $type type of beans - * @param array $ids ids to load + * @param int[] $ids ids to load * - * @return array + * @return OODBBean[] */ public static function loadAll( $type, $ids ) { @@ -13888,7 +13173,7 @@ class Facade * @param string $sql SQL query to execute * @param array $bindings a list of values to be bound to query parameters * - * @return array + * @return string[][] */ public static function getAll( $sql, $bindings = array() ) { @@ -13905,7 +13190,7 @@ class Facade * @param string $sql SQL query to execute * @param array $bindings a list of values to be bound to query parameters * - * @return string + * @return string|NULL */ public static function getCell( $sql, $bindings = array() ) { @@ -13922,7 +13207,7 @@ class Facade * @param string $sql SQL query to execute * @param array $bindings a list of values to be bound to query parameters * - * @return RedBeanPHP\Cursor\PDOCursor + * @return Cursor */ public static function getCursor( $sql, $bindings = array() ) { @@ -13939,7 +13224,7 @@ class Facade * @param string $sql SQL query to execute * @param array $bindings a list of values to be bound to query parameters * - * @return array + * @return array|NULL */ public static function getRow( $sql, $bindings = array() ) { @@ -13956,7 +13241,7 @@ class Facade * @param string $sql SQL query to execute * @param array $bindings a list of values to be bound to query parameters * - * @return array + * @return string[] */ public static function getCol( $sql, $bindings = array() ) { @@ -13975,7 +13260,7 @@ class Facade * @param string $sql SQL query to execute * @param array $bindings a list of values to be bound to query parameters * - * @return array + * @return string[] */ public static function getAssoc( $sql, $bindings = array() ) { @@ -13983,7 +13268,7 @@ class Facade } /** - *Convenience function to fire an SQL query using the RedBeanPHP + * Convenience function to fire an SQL query using the RedBeanPHP * database adapter. This method allows you to directly query the * database without having to obtain an database adapter instance first. * Executes the specified SQL query together with the specified @@ -14005,7 +13290,7 @@ class Facade * Returns the insert ID for databases that support/require this * functionality. Alias for R::getAdapter()->getInsertID(). * - * @return mixed + * @return int */ public static function getInsertID() { @@ -14031,12 +13316,12 @@ class Facade * This function has a confusing method signature, the R::duplicate() function * only accepts two arguments: bean and filters. * - * @param OODBBean $bean bean to be copied - * @param array $trail for internal usage, pass array() - * @param boolean $pid for internal usage - * @param array $filters white list filter with bean types to duplicate + * @param OODBBean $bean bean to be copied + * @param OODBBean[] $trail for internal usage, pass array() + * @param boolean $pid for internal usage + * @param array $filters white list filter with bean types to duplicate * - * @return array + * @return OODBBean */ public static function dup( $bean, $trail = array(), $pid = FALSE, $filters = array() ) { @@ -14063,10 +13348,10 @@ class Facade * Note: * This is a simplified version of the deprecated R::dup() function. * - * @param OODBBean $bean bean to be copied - * @param array $white white list filter with bean types to duplicate + * @param OODBBean $bean bean to be copied + * @param array $filters white list filter with bean types to duplicate * - * @return array + * @return OODBBean */ public static function duplicate( $bean, $filters = array() ) { @@ -14082,12 +13367,12 @@ class Facade * * all own bean lists (recursively) * * all shared beans (not THEIR own lists) * - * @param array|OODBBean $beans beans to be exported - * @param boolean $parents whether you want parent beans to be exported - * @param array $filters whitelist of types - * @param boolean $meta export meta data as well + * @param OODBBean|OODBBean[] $beans beans to be exported + * @param boolean $parents whether you want parent beans to be exported + * @param array $filters whitelist of types + * @param boolean $meta export meta data as well * - * @return array + * @return array[] */ public static function exportAll( $beans, $parents = FALSE, $filters = array(), $meta = FALSE ) { @@ -14147,14 +13432,14 @@ class Facade * New in 4.3.2: meta mask. The meta mask is a special mask to send * data from raw result rows to the meta store of the bean. This is * useful for bundling additional information with custom queries. - * Values of every column whos name starts with $mask will be + * Values of every column who's name starts with $mask will be * transferred to the meta section of the bean under key 'data.bundle'. * - * @param string $type type of beans to produce - * @param array $rows must contain an array of array - * @param string $metamask meta mask to apply (optional) + * @param string $type type of beans to produce + * @param string[][] $rows must contain an array of array + * @param string|array|NULL $metamask meta mask to apply (optional) * - * @return array + * @return OODBBean[] */ public static function convertToBeans( $type, $rows, $metamask = NULL ) { @@ -14162,11 +13447,11 @@ class Facade } /** - * Just like converToBeans, but for one bean. + * Just like convertToBeans, but for one bean. * - * @param string $type type of bean to produce - * @param array $row one row from the database - * @param string $metamask metamask (see convertToBeans) + * @param string $type type of bean to produce + * @param string[] $row one row from the database + * @param string|array|NULL $metamask metamask (see convertToBeans) * * @return OODBBean|NULL */ @@ -14216,7 +13501,7 @@ class Facade * @param string $type Type of bean to produce * @param string $sql SQL query snippet to use * @param array $bindings bindings for query (optional) - * @param mixed $metamask meta mask (optional, defaults to 'extra_') + * @param string|array $metamask meta mask (optional, defaults to 'extra_') * @param boolean $autoExtract TRUE to return meta mask values as first item of array * * @return array @@ -14260,9 +13545,9 @@ class Facade * or 'horror' this operation will return FALSE because the third parameter * has been set to TRUE. * - * @param OODBBean $bean bean to check for tags - * @param array|string $tags list of tags - * @param boolean $all whether they must all match or just some + * @param OODBBean $bean bean to check for tags + * @param string|string[] $tags list of tags + * @param boolean $all whether they must all match or just some * * @return boolean */ @@ -14287,8 +13572,8 @@ class Facade * In the example above, the $blog bean will no longer * be associated with the tags 'smart' and 'interesting'. * - * @param OODBBean $bean tagged bean - * @param array $tagList list of tags (names) + * @param OODBBean $bean tagged bean + * @param string|string[] $tagList list of tags (names) * * @return void */ @@ -14316,10 +13601,10 @@ class Facade * as 'TexMex' and 'Mexican Cuisine'. The second line will * retrieve all tags attached to the meal object. * - * @param OODBBean $bean bean to tag - * @param mixed $tagList tags to attach to the specified bean + * @param OODBBean $bean bean to tag + * @param string[]|NULL $tagList tags to attach to the specified bean * - * @return string + * @return string[] */ public static function tag( OODBBean $bean, $tagList = NULL ) { @@ -14341,8 +13626,8 @@ class Facade * The example adds the tag 'halloween' to the $blog * bean. * - * @param OODBBean $bean bean to tag - * @param array $tagList list of tags to add to bean + * @param OODBBean $bean bean to tag + * @param string|string[] $tagList list of tags to add to bean * * @return void */ @@ -14373,12 +13658,12 @@ class Facade * tagged as 'horror' or 'gothic', order them by title and limit * the number of movies to be returned to 10. * - * @param string $beanType type of bean you are looking for - * @param array|string $tagList list of tags to match - * @param string $sql additional SQL (use only for pagination) - * @param array $bindings bindings + * @param string $beanType type of bean you are looking for + * @param string|string[] $tagList list of tags to match + * @param string $sql additional SQL (use only for pagination) + * @param array $bindings bindings * - * @return array + * @return OODBBean[] */ public static function tagged( $beanType, $tagList, $sql = '', $bindings = array() ) { @@ -14407,12 +13692,12 @@ class Facade * The example above returns at most 4 movies (due to the LIMIT clause in the SQL * Query Snippet) that have been tagged as BOTH 'short' AND 'gothic'. * - * @param string $beanType type of bean you are looking for - * @param array|string $tagList list of tags to match - * @param string $sql additional sql snippet - * @param array $bindings bindings + * @param string $beanType type of bean you are looking for + * @param string|string[] $tagList list of tags to match + * @param string $sql additional sql snippet + * @param array $bindings bindings * - * @return array + * @return OODBBean[] */ public static function taggedAll( $beanType, $tagList, $sql = '', $bindings = array() ) { @@ -14424,10 +13709,10 @@ class Facade * * @see R::taggedAll * - * @param string $beanType type of bean you are looking for - * @param array|string $tagList list of tags to match - * @param string $sql additional sql snippet - * @param array $bindings bindings + * @param string $beanType type of bean you are looking for + * @param string|string[] $tagList list of tags to match + * @param string $sql additional sql snippet + * @param array $bindings bindings * * @return integer */ @@ -14441,10 +13726,10 @@ class Facade * * @see R::tagged * - * @param string $beanType type of bean you are looking for - * @param array|string $tagList list of tags to match - * @param string $sql additional sql snippet - * @param array $bindings bindings + * @param string $beanType type of bean you are looking for + * @param string|string[] $tagList list of tags to match + * @param string $sql additional sql snippet + * @param array $bindings bindings * * @return integer */ @@ -14504,7 +13789,7 @@ class Facade self::$labelMaker = new LabelMaker( self::$toolbox ); $helper = new SimpleModelHelper(); $helper->attachEventListeners( self::$redbean ); - if (self::$redbean->getBeanHelper() == NULL) { + if (self::$redbean->getBeanHelper() === NULL) { self::$redbean->setBeanHelper( new SimpleFacadeBeanHelper ); } self::$duplicationManager = new DuplicationManager( self::$toolbox ); @@ -14513,7 +13798,7 @@ class Facade } /** - * Facade Convience method for adapter transaction system. + * Facade Convenience method for adapter transaction system. * Begins a transaction. * * Usage: @@ -14554,7 +13839,7 @@ class Facade } /** - * Facade Convience method for adapter transaction system. + * Facade Convenience method for adapter transaction system. * Commits a transaction. * * Usage: @@ -14595,7 +13880,7 @@ class Facade } /** - * Facade Convience method for adapter transaction system. + * Facade Convenience method for adapter transaction system. * Rolls back a transaction. * * Usage: @@ -14643,7 +13928,7 @@ class Facade * * @param string $table name of the table (not type) you want to get columns of * - * @return array + * @return string[] */ public static function getColumns( $table ) { @@ -14675,7 +13960,7 @@ class Facade * ' IN( ?,? ) '. * * @param array $array array to generate question mark slots for - * @param string $template template to use + * @param string|NULL $template template to use * * @return string */ @@ -14709,11 +13994,11 @@ class Facade * ); * * - * @param array $beans a list of OODBBeans - * @param string $type a type string - * @param string $sqlTemplate an SQL template string for the SELECT-query + * @param OODBBean[]|TypedModel[] $beans a list of OODBBeans + * @param string $type a type string + * @param string $sqlTemplate an SQL template string for the SELECT-query * - * @return array + * @return OODBBean[]|TypedModel[] */ public static function loadJoined( $beans, $type, $sqlTemplate = 'SELECT %s.* FROM %s WHERE id IN (%s)' ) { @@ -14795,10 +14080,10 @@ class Facade * will automatically temporarily switch to fluid mode to attempt to store the * bean in case of an SQLException. * - * @param array $beans list of beans to be stored - * @param boolean $unfreezeIfNeeded retries in fluid mode in hybrid mode + * @param OODBBean[] $beans list of beans to be stored + * @param boolean $unfreezeIfNeeded retries in fluid mode in hybrid mode * - * @return array + * @return int[] ids */ public static function storeAll( $beans, $unfreezeIfNeeded = FALSE ) { @@ -14814,9 +14099,9 @@ class Facade * For information please consult the R::trash() function. * A loop saver. * - * @param array $beans list of beans to be trashed + * @param OODBBean[] $beans list of beans to be trashed * - * @return void + * @return int */ public static function trashAll( $beans ) { @@ -14832,13 +14117,13 @@ class Facade * only IDs. This function combines trashAll and batch loading * in one call. Note that while this function accepts just * bean IDs, the beans will still be loaded first. This is because - * the function still respects all the FUSE hooks that may have beeb + * the function still respects all the FUSE hooks that may have been * associated with the domain logic associated with these beans. * If you really want to delete just records from the database use * a simple DELETE-FROM SQL query instead. * - * @param string type $type the bean type you wish to trash - * @param string array $ids list of bean IDs + * @param string $type the bean type you wish to trash + * @param int[] $ids list of bean IDs * * @return void */ @@ -14864,9 +14149,9 @@ class Facade * * Returns the number of beans deleted. * - * @param string $type bean type to look for in database - * @param string $sqlSnippet an SQL query snippet - * @param array $bindings SQL parameter bindings + * @param string $type bean type to look for in database + * @param string|NULL $sqlSnippet an SQL query snippet + * @param array $bindings SQL parameter bindings * * @return int */ @@ -14907,10 +14192,10 @@ class Facade * values of the array will be assigned to the name property of each * individual bean. * - * @param string $type type of beans you would like to have - * @param array $labels list of labels, names for each bean + * @param string $type type of beans you would like to have + * @param string[] $labels list of labels, names for each bean * - * @return array + * @return OODBBean[] */ public static function dispenseLabels( $type, $labels ) { @@ -14919,7 +14204,7 @@ class Facade /** * Generates and returns an ENUM value. This is how RedBeanPHP handles ENUMs. - * Either returns a (newly created) bean respresenting the desired ENUM + * Either returns a (newly created) bean representing the desired ENUM * value or returns a list of all enums for the type. * * To obtain (and add if necessary) an ENUM value: @@ -14946,7 +14231,7 @@ class Facade * * @param string $enum either type or type-value * - * @return array|OODBBean + * @return OODBBean|OODBBean[] */ public static function enum( $enum ) { @@ -14959,9 +14244,9 @@ class Facade * and stores the names in a new array. The array then gets sorted using the * default sort function of PHP (sort). * - * @param array $beans list of beans to loop + * @param OODBBean[] $beans list of beans to loop * - * @return array + * @return string[] */ public static function gatherLabels( $beans ) { @@ -14995,7 +14280,7 @@ class Facade * Simple convenience function, returns ISO date formatted representation * of $time. * - * @param mixed $time UNIX timestamp + * @param int|NULL $time UNIX timestamp * * @return string */ @@ -15013,7 +14298,7 @@ class Facade * formatted representation * of $time. * - * @param mixed $time UNIX timestamp + * @param int|NULL $time UNIX timestamp * * @return string */ @@ -15069,7 +14354,7 @@ class Facade * Optional accessor for neat code. * Sets the database adapter you want to use. * - * @return DBAdapter + * @return Adapter */ public static function getDatabaseAdapter() { @@ -15088,7 +14373,7 @@ class Facade * If the PDO object could not be found, for whatever reason, this method * will return NULL instead. * - * @return NULL|PDO + * @return NULL|\PDO */ public static function getPDO() { @@ -15097,6 +14382,8 @@ class Facade $database = $databaseAdapter->getDatabase(); if ( is_null( $database ) ) return NULL; if ( !method_exists( $database, 'getPDO' ) ) return NULL; + + /** @var RPDO $database */ return $database->getPDO(); } @@ -15168,8 +14455,8 @@ class Facade /** * Facade method for AQueryWriter::renameAssociation() * - * @param string|array $from - * @param string $to + * @param string|string[] $from + * @param string $to * * @return void */ @@ -15185,9 +14472,9 @@ class Facade * and shared lists, the beans are exported as-is, only loaded lists * are exported. * - * @param array $beans beans + * @param OODBBean[] $beans beans * - * @return array + * @return array[] */ public static function beansToArray( $beans ) { @@ -15247,9 +14534,9 @@ class Facade * to 35 characters to improve readability. Nested beans will * also be dumped. * - * @param OODBBean|array $data either a bean or an array of beans + * @param OODBBean|OODBBean[] $data either a bean or an array of beans * - * @return array + * @return string|string[] */ public static function dump( $data ) { @@ -15291,7 +14578,7 @@ class Facade * fetchAs but explicitly. For instance if you register * the alias 'cover' for 'page' a property containing a reference to a * page bean called 'cover' will correctly return the page bean and not - * a (non-existant) cover bean. + * a (non-existent) cover bean. * * * R::aliases( array( 'cover' => 'page' ) ); @@ -15315,7 +14602,7 @@ class Facade * From that point on, every bean reference to a cover * will return a 'page' bean. * - * @param array $list list of global aliases to use + * @param string[] $list list of global aliases to use * * @return void */ @@ -15334,13 +14621,13 @@ class Facade * * @param string $type type of bean to search for * @param array $like criteria set describing the bean to search for - * @param boolean $hasBeenCreated set to TRUE if bean has been created + * @param boolean &$hasBeenCreated set to TRUE if bean has been created * * @return OODBBean */ public static function findOrCreate( $type, $like = array(), $sql = '', &$hasBeenCreated = false ) { - return self::$finder->findOrCreate( $type, $like, $sql = '', $hasBeenCreated ); + return self::$finder->findOrCreate( $type, $like, $sql, $hasBeenCreated ); } /** @@ -15355,7 +14642,7 @@ class Facade * @param string $sql optional additional SQL for sorting * @param array $bindings bindings * - * @return array + * @return OODBBean[] */ public static function findLike( $type, $like = array(), $sql = '', $bindings = array() ) { @@ -15398,7 +14685,7 @@ class Facade /** * Stops logging and flushes the logs, - * convient method to stop logging of queries. + * convenient method to stop logging of queries. * Use this method to stop logging SQL queries being * executed by the adapter. Logging queries will not * print them on the screen. Use R::getLogs() to @@ -15473,7 +14760,7 @@ class Facade * Therefore, only stop logging AFTER you have obtained the * query logs using R::getLogs() * - * @return array + * @return string[] */ public static function getLogs() { @@ -15524,7 +14811,7 @@ class Facade * Returns the current logger instance being used by the * database object. * - * @return Logger + * @return Logger|NULL */ public static function getLogger() { @@ -15546,9 +14833,9 @@ class Facade * for some types. * This method will return the previous value. * - * @param boolean|array $yesNoBeans List of type names or 'all' + * @param boolean|string[] $yesNoBeans List of type names or 'all' * - * @return mixed + * @return boolean|string[] */ public static function usePartialBeans( $yesNoBeans ) { @@ -15620,7 +14907,7 @@ class Facade * @param array $onNotFoundDo task list to be considered on NOT finding the bean * @param OODBBean &$bean reference to obtain the found bean * - * @return mixed + * @return bool|NULL */ public static function matchUp( $type, $sql, $bindings = array(), $onFoundDo = NULL, $onNotFoundDo = NULL, &$bean = NULL ) { $matchUp = new MatchUp( self::$toolbox ); @@ -15665,7 +14952,7 @@ class Facade * 'strtoupper', * "\n" * ); - * + * * * The example above creates an HTML fragment like this: * @@ -15724,11 +15011,10 @@ class Facade * of property names that have to be skipped. By default this array is filled with * two strings: 'created' and 'modified'. * - * @param OODBBean|array $bean reference beans - * @param OODBBean|array $other beans to compare + * @param OODBBean|OODBBean[] $bean reference beans + * @param OODBBean|OODBBean[] $other beans to compare * @param array $filters names of properties of all beans to skip - * @param string $format the format of the key, defaults to '%s.%s.%s' - * @param string $type type/property of bean to use for key generation + * @param string $pattern the format of the key, defaults to '%s.%s.%s' * * @return array */ @@ -15780,7 +15066,6 @@ class Facade * Returns the toolbox associated with the specified key. * * @param string $key key to store toolbox instance under - * @param ToolBox $toolbox toolbox to register * * @return ToolBox|NULL */ @@ -15838,7 +15123,7 @@ class Facade /** * Given a bean and an optional SQL snippet, - * this method will return the bean together with all + * this method will return the bean together with all * child beans in a hierarchically structured * bean table. * @@ -15847,9 +15132,11 @@ class Facade * a warning mechanism in case your database does not support this * functionality. * - * @param OODBBean $bean bean to find children of - * @param string $sql optional SQL snippet - * @param array $bindings SQL snippet parameter bindings + * @param OODBBean $bean bean to find children of + * @param string|NULL $sql optional SQL snippet + * @param array $bindings SQL snippet parameter bindings + * + * @return OODBBean[] */ public static function children( OODBBean $bean, $sql = NULL, $bindings = array() ) { @@ -15880,9 +15167,11 @@ class Facade * it cannot 'predict' what or how you are trying to 'count'. * * @param OODBBean $bean bean to find children of - * @param string $sql optional SQL snippet + * @param string|NULL $sql optional SQL snippet * @param array $bindings SQL snippet parameter bindings * @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression) + * + * @return int */ public static function countChildren( OODBBean $bean, $sql = NULL, $bindings = array(), $select = QueryWriter::C_CTE_SELECT_COUNT ) { @@ -15913,9 +15202,11 @@ class Facade * it cannot 'predict' what or how you are trying to 'count'. * * @param OODBBean $bean bean to find children of - * @param string $sql optional SQL snippet + * @param string|NULL $sql optional SQL snippet * @param array $bindings SQL snippet parameter bindings * @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression) + * + * @return int */ public static function countParents( OODBBean $bean, $sql = NULL, $bindings = array(), $select = QueryWriter::C_CTE_SELECT_COUNT ) { @@ -15932,9 +15223,11 @@ class Facade * a warning mechanism in case your database does not support this * functionality. * - * @param OODBBean $bean bean to find parents of - * @param string $sql optional SQL snippet - * @param array $bindings SQL snippet parameter bindings + * @param OODBBean $bean bean to find parents of + * @param string|NULL $sql optional SQL snippet + * @param array $bindings SQL snippet parameter bindings + * + * @return OODBBean[] */ public static function parents( OODBBean $bean, $sql = NULL, $bindings = array() ) { @@ -15954,6 +15247,58 @@ class Facade return AQueryWriter::forbidNuke( $yesNo ); } + /** + * Globally available service method for RedBeanPHP. + * Converts a snake cased string to a camel cased string. + * If the parameter is an array, the keys will be converted. + * + * @param string|array $snake snake_cased string to convert to camelCase + * @param boolean $dolphin exception for Ids - (bookId -> bookID) + * too complicated for the human mind, only dolphins can understand this + * + * @return string|array + */ + public static function camelfy( $snake, $dolphin = false ) + { + if ( is_array( $snake ) ) { + $newArray = array(); + foreach( $snake as $key => $value ) { + $newKey = self::camelfy( $key, $dolphin ); + if ( is_array( $value ) ) { + $value = self::camelfy( $value, $dolphin ); + } + $newArray[ $newKey ] = $value; + } + return $newArray; + } + return AQueryWriter::snakeCamel( $snake, $dolphin ); + } + + /** + * Globally available service method for RedBeanPHP. + * Converts a camel cased string to a snake cased string. + * If the parameter is an array, the keys will be converted. + * + * @param string|array $camel camelCased string to convert to snake case + * + * @return string|array + */ + public static function uncamelfy( $camel ) + { + if ( is_array( $camel ) ) { + $newArray = array(); + foreach( $camel as $key => $value ) { + $newKey = self::uncamelfy( $key ); + if ( is_array( $value ) ) { + $value = self::uncamelfy( $value ); + } + $newArray[ $newKey ] = $value; + } + return $newArray; + } + return AQueryWriter::camelsSnake( $camel ); + } + /** * Selects the feature set you want as specified by * the label. @@ -16090,7 +15435,7 @@ class DuplicationManager protected $filters = array(); /** - * @var array + * @var boolean */ protected $cacheTables = FALSE; @@ -16300,7 +15645,7 @@ class DuplicationManager public function camelfy( $array, $dolphinMode = FALSE ) { $newArray = array(); foreach( $array as $key => $element ) { - $newKey = preg_replace_callback( '/_(\w)/', function( &$matches ){ + $newKey = preg_replace_callback( '/_(\w)/', function( $matches ){ return strtoupper( $matches[1] ); }, $key); @@ -16367,6 +15712,8 @@ class DuplicationManager * every time a duplication action is performed (dup()). * * @param boolean $yesNo TRUE to use caching, FALSE otherwise + * + * @return void */ public function setCacheTables( $yesNo ) { @@ -16544,8 +15891,8 @@ class ArrayTool * The statement in the example will produce the string: * ' IN( ?,? ) '. * - * @param array $array array to generate question mark slots for - * @param string $template template to use + * @param array $array array to generate question mark slots for + * @param string|NULL $template template to use * * @return string */ @@ -16585,13 +15932,14 @@ class ArrayTool namespace RedBeanPHP\Util { use RedBeanPHP\OODB as OODB; +use RedBeanPHP\OODBBean as OODBBean; use RedBeanPHP\RedException as RedException; /** * Dispense Helper * * A helper class containing a dispense utility. - * + * * @file RedBeanPHP/Util/DispenseHelper.php * @author Gabor de Mooij and the RedBeanPHP Community * @license BSD/GPLv2 @@ -16704,7 +16052,7 @@ class DispenseHelper * @param integer $num number of beans to dispense * @param boolean $alwaysReturnArray if TRUE always returns the result as an array * - * @return array|OODBBean + * @return OODBBean|OODBBean[] */ public static function dispense( OODB $oodb, $typeOrBeanArray, $num = 1, $alwaysReturnArray = FALSE ) { @@ -16864,6 +16212,7 @@ class Dump namespace RedBeanPHP\Util { use RedBeanPHP\OODB as OODB; +use RedBeanPHP\OODBBean as OODBBean; /** * Multi Bean Loader Helper @@ -16874,7 +16223,7 @@ use RedBeanPHP\OODB as OODB; * * This helper class offers limited support for one-to-one * relations by providing a service to load a set of beans - * with differnt types and a common ID. + * with different types and a common ID. * * @file RedBeanPHP/Util/MultiLoader.php * @author Gabor de Mooij and the RedBeanPHP Community @@ -16905,7 +16254,7 @@ class MultiLoader * @param string|array $types the set of types to load at once * @param mixed $id the common ID * - * @return OODBBean + * @return OODBBean[] */ public static function load( OODB $oodb, $types, $id ) { @@ -17021,7 +16370,7 @@ use RedBeanPHP\ToolBox as ToolBox; * The Quick Export Utility Class provides functionality to easily * expose the result of SQL queries as well-known formats like CSV. * - * @file RedBeanPHP/Util/QuickExporft.php + * @file RedBeanPHP/Util/QuickExport.php * @author Gabor de Mooij and the RedBeanPHP Community * @license BSD/GPLv2 * @@ -17033,12 +16382,12 @@ use RedBeanPHP\ToolBox as ToolBox; class QuickExport { /** - * @var Finder + * @var ToolBox */ protected $toolbox; /** - * @boolean + * @var boolean */ private static $test = FALSE; @@ -17055,7 +16404,13 @@ class QuickExport /** * Makes csv() testable. - */ + * + * @param string $name + * @param mixed $arg1 + * @param boolean $arg2 + * + * @return mixed + */ public static function operation( $name, $arg1, $arg2 = TRUE ) { $out = ''; switch( $name ) { @@ -17104,7 +16459,7 @@ class QuickExport * @param boolean $output TRUE to output CSV directly using readfile * @param array $options delimiter, quote and escape character respectively * - * @return void + * @return string|NULL */ public function csv( $sql = '', $bindings = array(), $columns = NULL, $path = '/tmp/redexport_%s.csv', $output = TRUE, $options = array(',','"','\\') ) { @@ -17214,11 +16569,11 @@ class MatchUp * @param string $type type of bean you're looking for * @param string $sql SQL snippet (starting at the WHERE clause, omit WHERE-keyword) * @param array $bindings array of parameter bindings for SQL snippet - * @param array $onFoundDo task list to be considered on finding the bean - * @param array $onNotFoundDo task list to be considered on NOT finding the bean - * @param OODBBean &$bean reference to obtain the found bean + * @param array|NULL $onFoundDo task list to be considered on finding the bean + * @param array|NULL $onNotFoundDo task list to be considered on NOT finding the bean + * @param OODBBean|NULL &$bean reference to obtain the found bean * - * @return mixed + * @return bool|NULL */ public function matchUp( $type, $sql, $bindings = array(), $onFoundDo = NULL, $onNotFoundDo = NULL, &$bean = NULL ) { @@ -17374,7 +16729,7 @@ use RedBeanPHP\Finder; * * The Look Utility class provides an easy way to generate * tables and selects (pulldowns) from the database. - * + * * @file RedBeanPHP/Util/Diff.php * @author Gabor de Mooij and the RedBeanPHP Community * @license BSD/GPLv2 @@ -17430,7 +16785,7 @@ class Diff * @param OODBBean|array $others beans to compare * @param array $filters names of properties of all beans to skip * @param string $format the format of the key, defaults to '%s.%s.%s' - * @param string $type type/property of bean to use for key generation + * @param string|NULL $type type/property of bean to use for key generation * * @return array */ @@ -17481,13 +16836,15 @@ class Diff namespace RedBeanPHP\Util { use RedBeanPHP\ToolBox; +use RedBeanPHP\OODB; use RedBeanPHP\OODBBean; +use RedBeanPHP\QueryWriter; /** * Tree * * Given a bean, finds it children or parents - * in a hierchical structure. + * in a hierarchical structure. * * @experimental feature * @@ -17535,12 +16892,12 @@ class Tree { * bean in a tree structure. * * @note this only works for databases that support - * recusrive common table expressions. - * + * recursive common table expressions. + * * Usage: * * - * $newsArticles = R::children( $newsPage, ' ORDER BY title ASC ' ) + * $newsArticles = R::children( $newsPage, ' ORDER BY title ASC ' ) * $newsArticles = R::children( $newsPage, ' WHERE title = ? ', [ $t ] ); * $newsArticles = R::children( $newsPage, ' WHERE title = :t ', [ ':t' => $t ] ); * @@ -17552,9 +16909,9 @@ class Tree { * parameter binding key ':slot0' is reserved for the ID of the bean * and used in the query. * - * @param OODBBean $bean reference bean to find children of - * @param string $sql optional SQL snippet - * @param array $bindings optional parameter bindings for SQL snippet + * @param OODBBean $bean reference bean to find children of + * @param string|NULL $sql optional SQL snippet + * @param array $bindings optional parameter bindings for SQL snippet * * @return array */ @@ -17573,7 +16930,7 @@ class Tree { * bean in a tree structure. * * @note this only works for databases that support - * recusrive common table expressions. + * recursive common table expressions. * * * $newsPages = R::parents( $newsArticle, ' ORDER BY title ASC ' ); @@ -17588,9 +16945,9 @@ class Tree { * parameter binding key ':slot0' is reserved for the ID of the bean * and used in the query. * - * @param OODBBean $bean reference bean to find parents of - * @param string $sql optional SQL snippet - * @param array $bindings optional parameter bindings for SQL snippet + * @param OODBBean $bean reference bean to find parents of + * @param string|NULL $sql optional SQL snippet + * @param array $bindings optional parameter bindings for SQL snippet * * @return array */ @@ -17609,7 +16966,7 @@ class Tree { * bean in a tree structure. * * @note this only works for databases that support - * recusrive common table expressions. + * recursive common table expressions. * * * $count = R::countChildren( $newsArticle ); @@ -17631,7 +16988,7 @@ class Tree { * it cannot 'predict' what or how you are trying to 'count'. * * @param OODBBean $bean reference bean to find children of - * @param string $sql optional SQL snippet + * @param string|NULL $sql optional SQL snippet * @param array $bindings optional parameter bindings for SQL snippet * @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression) * @@ -17651,7 +17008,7 @@ class Tree { * bean in a tree structure. * * @note this only works for databases that support - * recusrive common table expressions. + * recursive common table expressions. * * * $count = R::countParents( $newsArticle ); @@ -17672,9 +17029,9 @@ class Tree { * this method assumes you take control of the resulting total yourself since * it cannot 'predict' what or how you are trying to 'count'. * - * @param OODBBean $bean reference bean to find parents of - * @param string $sql optional SQL snippet - * @param array $bindings optional parameter bindings for SQL snippet + * @param OODBBean $bean reference bean to find parents of + * @param string|NULL $sql optional SQL snippet + * @param array $bindings optional parameter bindings for SQL snippet * @param string|boolean $select select snippet to use (advanced, optional, see QueryWriter::queryRecursiveCommonTableExpression) * * @return integer @@ -17759,7 +17116,7 @@ class Feature case self::C_FEATURE_NOVICE_LATEST: case self::C_FEATURE_NOVICE_5_4: case self::C_FEATURE_NOVICE_5_5: - OODBBean::useFluidCount( FALSE ); + OODBBean::useFluidCount( TRUE ); R::noNuke( TRUE ); R::setAllowHybridMode( FALSE ); R::useISNULLConditions( TRUE ); @@ -17767,7 +17124,7 @@ class Feature case self::C_FEATURE_LATEST: case self::C_FEATURE_5_4: case self::C_FEATURE_5_5: - OODBBean::useFluidCount( FALSE ); + OODBBean::useFluidCount( TRUE ); R::noNuke( FALSE ); R::setAllowHybridMode( TRUE ); R::useISNULLConditions( TRUE ); @@ -17798,6 +17155,158 @@ class Feature } } +namespace RedBeanPHP\Util { + +/** + * Either Utility + * + * The Either Utility class provides an easy way to + * substitute the NULL coalesce operator in RedBeanPHP + * (since the lazy loading interface interferes with the ?? + * operator) in a way that can also be used in older PHP-versions. + * + * @file RedBeanPHP/Util/Either.php + * @author Gabor de Mooij and the RedBeanPHP Community + * @license BSD/GPLv2 + * + * @copyright + * copyright (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community + * This source file is subject to the BSD/GPLv2 License that is bundled + * with this source code in the file license.txt. + */ +class Either { + + /** + * @var mixed + */ + private $result; + + /** + * Constructs a new Either-instance. + * + * Example usage: + * + * + * $author = $text + * ->either() + * ->page + * ->book + * ->autor + * ->name + * ->or('unknown'); + * + * + * The Either-class lets you access bean properties without having to do + * NULL-checks. The mechanism resembles the use of the ?? somewhat but + * offers backward compatibility with older PHP versions. The mechanism also works + * on arrays. + * + * + * $budget = $company + * ->either() + * ->sharedProject + * ->first() + * ->budget + * ->or(0); + * + */ + public function __construct($result) { + $this->result = $result; + } + + /** + * Extracts a value from the wrapped object and stores + * it in the internal result object. If the desired + * value cannot be found, the internal result object will be set + * to NULL. Chainable. + * + * @param string $something name of the property you wish to extract the value of + * + * @return self + */ + public function __get($something) { + if (is_object($this->result)) { + $this->result = $this->result->{$something}; + } else { + $this->result = NULL; + } + return $this; + } + + /** + * Extracts the first element of the array in the internal result + * object and stores it as the new value of the internal result object. + * Chainable. + * + * @return self + */ + public function first() { + if (is_array($this->result)) { + reset($this->result); + $key = key($this->result); + if (isset($this->result[$key])) { + $this->result = $this->result[$key]; + } else { + $this->result = NULL; + } + } + return $this; + } + + /** + * Extracts the last element of the array in the internal result + * object and stores it as the new value of the internal result object. + * Chainable. + * + * @return self + */ + public function last() { + if (is_array($this->result)) { + end($this->result); + $key = key($this->result); + if (isset($this->result[$key])) { + $this->result = $this->result[$key]; + } else { + $this->result = NULL; + } + } + return $this; + } + + /** + * Extracts the specified element of the array in the internal result + * object and stores it as the new value of the internal result object. + * Chainable. + * + * @return self + */ + public function index( $key = 0 ) { + if (is_array($this->result)) { + if (isset($this->result[$key])) { + $this->result = $this->result[$key]; + } else { + $this->result = NULL; + } + } + return $this; + } + + /** + * Resolves the Either-instance to a final value, either the value + * contained in the internal result object or the value specified + * in the or() function. + * + * @param mixed $value value to resolve to if internal result equals NULL + * + * @return mixed + */ + public function _or( $value ) { + $reference = (is_null($this->result)) ? $value : $this->result; + return $reference; + } +} +} + namespace RedBeanPHP { /** @@ -17911,5 +17420,61 @@ if ( !function_exists( 'array_flatten' ) ) { } } +/** + * Function pstr() generates [ $value, \PDO::PARAM_STR ] + * Ensures that your parameter is being treated as a string. + * + * Usage: + * + * + * R::find('book', 'title = ?', [ pstr('1') ]); + * + */ +if ( !function_exists( 'pstr' ) ) { + + function pstr( $value ) + { + return array( strval( $value ) , \PDO::PARAM_STR ); + } +} + + +/** + * Function pint() generates [ $value, \PDO::PARAM_INT ] + * Ensures that your parameter is being treated as an integer. + * + * Usage: + * + * + * R::find('book', ' pages > ? ', [ pint(2) ] ); + * + */ +if ( !function_exists( 'pint' ) ) { + + function pint( $value ) + { + return array( intval( $value ) , \PDO::PARAM_INT ); + } +} + +/** + * Function DBPrefix() is a simple function to allow you to + * quickly set a different namespace for FUSE model resolution + * per database connection. It works by creating a new DynamicBeanHelper + * with the specified string as model prefix. + * + * Usage: + * + * + * R::addDatabase( ..., DBPrefix( 'Prefix1_' ) ); + * + */ +if ( !function_exists( 'DBPrefix' ) ) { + + function DBPrefix( $prefix = '\\Model' ) { + return new \RedBeanPHP\BeanHelper\DynamicBeanHelper( $prefix ); + } +} + } diff --git a/templates/.DS_Store b/templates/.DS_Store deleted file mode 100644 index 96797d4..0000000 Binary files a/templates/.DS_Store and /dev/null differ diff --git a/templates/shop-order/payment-confirmation.php b/templates/shop-order/payment-confirmation.php index 13e789b..597b130 100644 --- a/templates/shop-order/payment-confirmation.php +++ b/templates/shop-order/payment-confirmation.php @@ -1,4 +1,4 @@ - order['status'] == 1 ):?> + order['status'] == 1 or $this -> order['status'] == 4 ):?>
Płatność została zatwierdzona. Dziękujemy za wybranie naszych usług.
Nasz system zweryfikuje Państwa zamówienie w ciągu kilku minut.
@@ -24,8 +24,26 @@
- - settings['ekomi_survey'] ):?> - - settings['ekomi_survey'];?> + +
+
Płatność oczekuje na zatwierdzenie.
+
Nasz system zweryfikuje Państwa zamówienie w ciągu kilku minut.
+

+ + + + + + + + + + + + + + + + +
Informacje o płatności
Zamówienie nr: order['number'];?>
Data transakcji: order['date_order'] ) );?>