'int', 'title' => 'string', 'content' => 'string', 'rating' => 'int', 'status' => 'string', 'recipe_id' => 'int', 'user_id' => 'int', 'created_at' => 'DateTime', ]; static protected $additional_fields = array( [ 'field' => [ 'us.username AS author_username' ], 'join_table' => 'users us ON us.id = obj.user_id' ], [ 'field' => [ 're.title AS recipe_title', 're.image_url AS recipe_image' ], 'join_table' => 'recipes re ON re.id = obj.recipe_id' ] ); public static function init_table() { $result = db_query('CREATE TABLE ' . static::$table_name . ' ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, rating INT NOT NULL, status VARCHAR(20) NOT NULL CHECK (status IN (\'publish\', \'pending\')), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, recipe_id INT NOT NULL, user_id INT NOT NULL, FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE );'); return $result; } public function get_html_content(): string { return nl2br(trim($this->field_content)); } public function get_status() { return ucfirst($this->field_status); } public function get_date() { $date = new DateTime($this->field_created_at); return $date->format('d.m.Y'); } public function get_excerpt() { $max_length = 100; $excerpt = mb_substr($this->field_content, 0, $max_length); if(mb_strlen($this->field_content) > $max_length) $excerpt .= '...'; return $excerpt; } public function get_recipe_image() { $recipe = new RecipeModel(); $recipe->field_image_url = $this->recipe_image; return $recipe->get_image_url(); } public function valid() { $errors = array(); if(empty($this->field_title)) $errors[] = 'Title field is empty'; if(empty($this->field_content)) $errors[] = 'Content field is empty'; $this->field_rating = (int)$this->field_rating; if($this->field_rating < 1 || $this->field_rating > 5) { $errors[] = 'Rating must be between 1 and 5'; } if (empty($errors)) return true; return $errors; } }