Merge branch 'develop'
This commit is contained in:
		
						commit
						1bf3fba756
					
				
							
								
								
									
										149
									
								
								README.markdown
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								README.markdown
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | |||||||
|  | ``` | ||||||
|  |      _________.__     .__                   .__         ________    | ||||||
|  |     /   _____/|  |__  |__|  _____    _____  |__|  ____  \_____  \   | ||||||
|  |     \_____  \ |  |  \ |  | /     \  /     \ |  |_/ __ \  /  ____/   | ||||||
|  |     /        \|   Y  \|  ||  Y Y  \|  Y Y  \|  |\  ___/ /       \   | ||||||
|  |    /_______  /|___|  /|__||__|_|  /|__|_|  /|__| \___  >\_______ \  | ||||||
|  |            \/      \/           \/       \/          \/         \/  | ||||||
|  |                                                                  | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | # Shimmie | ||||||
|  | 
 | ||||||
|  | [](https://travis-ci.org/shish/shimmie2) | ||||||
|  | 
 | ||||||
|  | This is the main branch of Shimmie, if you know anything at all about running | ||||||
|  | websites, this is the version to use. | ||||||
|  | 
 | ||||||
|  | Alternatively if you want a version that will never have significant changes, | ||||||
|  | check out one of the versioned branches. | ||||||
|  | 
 | ||||||
|  | # Requirements | ||||||
|  | 
 | ||||||
|  | - MySQL/MariaDB 5.1+ (with experimental support for PostgreSQL 8+ and SQLite 3) | ||||||
|  | - PHP 5.3.7+ | ||||||
|  | - GD or ImageMagick | ||||||
|  | 
 | ||||||
|  | # Installation | ||||||
|  | 
 | ||||||
|  | 1. Create a blank database | ||||||
|  | 2. Unzip shimmie into a folder on the web host | ||||||
|  | 3. Visit the folder with a web browser | ||||||
|  | 4. Enter the location of the database | ||||||
|  | 5. Click "install". Hopefully you'll end up at the welcome screen; if | ||||||
|  |    not, you should be given instructions on how to fix any errors~ | ||||||
|  | 
 | ||||||
|  | ## Upgrade from 2.3.X | ||||||
|  | 
 | ||||||
|  | 1. Backup your current files and database! | ||||||
|  | 2. Unzip into a clean folder | ||||||
|  | 3. Copy across the images, thumbs, and data folders | ||||||
|  | 4. Move `old/config.php` to `new/data/config/shimmie.conf.php` | ||||||
|  | 5. Edit `shimmie.conf.php` to use the new database connection format: | ||||||
|  | 
 | ||||||
|  | OLD Format: | ||||||
|  | ```php | ||||||
|  | $database_dsn = "<proto>://<username>:<password>@<host>/<database>"; | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | NEW Format: | ||||||
|  | ```php | ||||||
|  | define("DATABASE_DSN", "<proto>:user=<username>;password=<password>;host=<host>;dbname=<database>"); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The rest should be automatic~ | ||||||
|  | 
 | ||||||
|  | If there are any errors with the upgrade process, `in_upgrade=true` will | ||||||
|  | be left in the config table and the process will be paused for the admin | ||||||
|  | to investigate. | ||||||
|  | 
 | ||||||
|  | Deleting this config entry and refreshing the page should continue the upgrade from where it left off. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### Upgrade from earlier versions | ||||||
|  | 
 | ||||||
|  | I very much recommend going via each major release in turn (eg, 2.0.6 | ||||||
|  | -> 2.1.3 -> 2.2.4 -> 2.3.0 rather than 2.0.6 -> 2.3.0). | ||||||
|  | 
 | ||||||
|  | While the basic database and file formats haven't changed *completely*, it's different | ||||||
|  | enough to be a pain. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## Custom Configuration | ||||||
|  | 
 | ||||||
|  | Various aspects of Shimmie can be configured to suit your site specific needs | ||||||
|  | via the file `data/config/shimmie.conf.php` (created after installation). | ||||||
|  | 
 | ||||||
|  | Take a look at `core/sys_config.inc.php` for the available options that can | ||||||
|  | be used. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #### Custom User Classes | ||||||
|  | 
 | ||||||
|  | User classes can be added to or altered by placing them in | ||||||
|  | `data/config/user-classes.conf.php`. | ||||||
|  | 
 | ||||||
|  | For example, one can override the default anonymous "allow nothing" permissions like so: | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | new UserClass("anonymous", "base", array( | ||||||
|  | 	"create_comment" => True, | ||||||
|  | 	"edit_image_tag" => True, | ||||||
|  | 	"edit_image_source" => True, | ||||||
|  | 	"create_image_report" => True, | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | For a moderator class, being a regular user who can delete images and comments: | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | new UserClass("moderator", "user", array( | ||||||
|  | 	"delete_image" => True, | ||||||
|  | 	"delete_comment" => True, | ||||||
|  | )); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | For a list of permissions, see `core/userclass.class.php` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Development Info | ||||||
|  | 
 | ||||||
|  | ui-* cookies are for the client-side scripts only; in some configurations | ||||||
|  | (eg with varnish cache) they will be stripped before they reach the server | ||||||
|  | 
 | ||||||
|  | shm-* CSS classes are for javascript to hook into; if you're customising | ||||||
|  | themes, be careful with these, and avoid styling them, eg: | ||||||
|  | 
 | ||||||
|  | - shm-thumb = outermost element of a thumbnail | ||||||
|  |    * data-tags | ||||||
|  |    * data-post-id | ||||||
|  | - shm-toggler = click this to toggle elements that match the selector | ||||||
|  |   * data-toggle-sel | ||||||
|  | - shm-unlocker = click this to unlock elements that match the selector | ||||||
|  |   * data-unlock-sel | ||||||
|  | - shm-clink = a link to a comment, flash the target element when clicked | ||||||
|  |   * data-clink-sel | ||||||
|  | 
 | ||||||
|  | Documentation: http://shimmie.shishnet.org/doc/ | ||||||
|  | 
 | ||||||
|  | Please tell me if those docs are lacking in any way, so that they can be | ||||||
|  | improved for the next person who uses them | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Contact | ||||||
|  | 
 | ||||||
|  | IRC: `#shimmie` on [Freenode](irc.freenode.net) | ||||||
|  | 
 | ||||||
|  | Email: webmaster at shishnet.org | ||||||
|  | 
 | ||||||
|  | Issue/Bug tracker: http://github.com/shish/shimmie2/issues | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Licence | ||||||
|  | 
 | ||||||
|  | All code is released under the [GNU GPL Version 2](http://www.gnu.org/licenses/gpl-2.0.html) unless mentioned otherwise. | ||||||
|  | 
 | ||||||
|  | If you give shimmie to someone else, you have to give them the source (which should be easy, as PHP | ||||||
|  | is an interpreted language...). If you want to add customisations to your own | ||||||
|  | site, then those customisations belong to you, and you can do what you want | ||||||
|  | with them. | ||||||
							
								
								
									
										133
									
								
								README.txt
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								README.txt
									
									
									
									
									
								
							| @ -1,133 +0,0 @@ | |||||||
| 
 |  | ||||||
|      _________.__     .__                   .__         ________    |  | ||||||
|     /   _____/|  |__  |__|  _____    _____  |__|  ____  \_____  \   |  | ||||||
|     \_____  \ |  |  \ |  | /     \  /     \ |  |_/ __ \  /  ____/   |  | ||||||
|     /        \|   Y  \|  ||  Y Y  \|  Y Y  \|  |\  ___/ /       \   |  | ||||||
|    /_______  /|___|  /|__||__|_|  /|__|_|  /|__| \___  >\_______ \  |  | ||||||
|            \/      \/           \/       \/          \/         \/  |  | ||||||
|                                                                  |  | ||||||
| _________________________________________________________________________ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Shimmie Development |  | ||||||
| ~~~~~~~~~~~~~~~~~~~ |  | ||||||
| This is the main branch of Shimmie, if you know anything at all about |  | ||||||
| running websites, this is the version to use. Alternatively if you want |  | ||||||
| a version that will never have significant changes, check out one of the |  | ||||||
| versioned branches. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Requirements |  | ||||||
| ~~~~~~~~~~~~ |  | ||||||
| MySQL/MariaDB 5.1+ (with experimental support for PostgreSQL 8+ and SQLite 3) |  | ||||||
| PHP 5.3+ |  | ||||||
| GD or ImageMagick |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Installation |  | ||||||
| ~~~~~~~~~~~~ |  | ||||||
| 1) Create a blank database |  | ||||||
| 2) Unzip shimmie into a folder on the web host |  | ||||||
| 3) Visit the folder with a web browser |  | ||||||
| 4) Enter the location of the database |  | ||||||
| 5) Click "install". Hopefully you'll end up at the welcome screen; if |  | ||||||
|    not, you should be given instructions on how to fix any errors~ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Upgrade from 2.3.X |  | ||||||
| ~~~~~~~~~~~~~~~~~~ |  | ||||||
| - Backup your current files and database! |  | ||||||
| - Unzip into a clean folder |  | ||||||
| - Copy across the images, thumbs, and data folders |  | ||||||
| - Move old/config.php to new/data/config/shimmie.conf.php |  | ||||||
| - Edit shimmie.conf.php to use the new database connection format: |  | ||||||
| 
 |  | ||||||
|  OLD: $database_dsn = "<proto>://<username>:<password>@<host>/<database>"; |  | ||||||
|  NEW: define("DATABASE_DSN", "<proto>:user=<username>;password=<password>;host=<host>;dbname=<database>"); |  | ||||||
| 
 |  | ||||||
| The rest should be automatic~ |  | ||||||
| 
 |  | ||||||
| If there are any errors with the upgrade process, "in_upgrade=true" will |  | ||||||
| be left in the config table and the process will be paused for the admin |  | ||||||
| to investigate. Deleting this config entry and refreshing the page should |  | ||||||
| continue the upgrade from where it left off. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Upgrade from earlier versions |  | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |  | ||||||
| I very much recommend going via each major release in turn (eg, 2.0.6 |  | ||||||
| -> 2.1.3 -> 2.2.4 -> 2.3.0 rather than 2.0.6 -> 2.3.0). While the basic |  | ||||||
| database and file formats haven't changed *completely*, it's different |  | ||||||
| enough to be a pain. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Custom Configuration |  | ||||||
| ~~~~~~~~~~~~~~~~~~~~ |  | ||||||
| Various aspects of Shimmie can be configured to suit your site specific needs |  | ||||||
| via the file "data/config/shimmie.conf.php" (created after installation). |  | ||||||
| Take a look at "core/sys_config.inc.php" for the available options that can |  | ||||||
| be used. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Custom User Classes |  | ||||||
| ~~~~~~~~~~~~~~~~~~~ |  | ||||||
| User classes can be added to or altered by placing them in |  | ||||||
| `data/config/user-classes.conf.php`. For example, one can override the |  | ||||||
| default anonymous "allow nothing" permissions like so: |  | ||||||
| 
 |  | ||||||
| new UserClass("anonymous", "base", array( |  | ||||||
| 	"create_comment" => True, |  | ||||||
| 	"edit_image_tag" => True, |  | ||||||
| 	"edit_image_source" => True, |  | ||||||
| 	"create_image_report" => True, |  | ||||||
| )); |  | ||||||
| 
 |  | ||||||
| For a moderator class, being a regular user who can delete images and |  | ||||||
| comments: |  | ||||||
| 
 |  | ||||||
| new UserClass("moderator", "user", array( |  | ||||||
| 	"delete_image" => True, |  | ||||||
| 	"delete_comment" => True, |  | ||||||
| )); |  | ||||||
| 
 |  | ||||||
| For a list of permissions, see core/userclass.class.php |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Development Info |  | ||||||
| ~~~~~~~~~~~~~~~~ |  | ||||||
| ui-* cookies are for the client-side scripts only; in some configurations |  | ||||||
| (eg with varnish cache) they will be stripped before they reach the server |  | ||||||
| 
 |  | ||||||
| shm-* CSS classes are for javascript to hook into; if you're customising |  | ||||||
| themes, be careful with these, and avoid styling them, eg: |  | ||||||
| 
 |  | ||||||
| - shm-thumb = outermost element of a thumbnail |  | ||||||
|    - data-tags |  | ||||||
|    - data-post-id |  | ||||||
| - shm-toggler = click this to toggle elements that match the selector |  | ||||||
|   - data-toggle-sel |  | ||||||
| - shm-unlocker = click this to unlock elements that match the selector |  | ||||||
|   - data-unlock-sel |  | ||||||
| - shm-clink = a link to a comment, flash the target element when clicked |  | ||||||
|   - data-clink-sel |  | ||||||
| 
 |  | ||||||
| http://shimmie.shishnet.org/doc/ |  | ||||||
| 
 |  | ||||||
| Please tell me if those docs are lacking in any way, so that they can be |  | ||||||
| improved for the next person who uses them |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Contact |  | ||||||
| ~~~~~~~ |  | ||||||
| #shimmie on Freenode -- IRC |  | ||||||
| webmaster at shishnet.org -- email |  | ||||||
| https://github.com/shish/shimmie2/issues -- bug tracker |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Licence |  | ||||||
| ~~~~~~~ |  | ||||||
| All code is GPLv2 unless mentioned otherwise; ie, if you give shimmie to |  | ||||||
| someone else, you have to give them the source (which should be easy, as PHP |  | ||||||
| is an interpreted language...). If you want to add customisations to your own |  | ||||||
| site, then those customisations belong to you, and you can do what you want |  | ||||||
| with them. |  | ||||||
| @ -56,7 +56,7 @@ class BaseThemelet { | |||||||
| 		$h_tip = html_escape($image->get_tooltip()); | 		$h_tip = html_escape($image->get_tooltip()); | ||||||
| 		$h_tags = strtolower($image->get_tag_list()); | 		$h_tags = strtolower($image->get_tag_list()); | ||||||
| 
 | 
 | ||||||
| 		$extArr = array_flip(array('swf', 'svg', 'mp4', 'ogv', 'webm', 'flv')); //List of thumbless filetypes
 | 		$extArr = array_flip(array('swf', 'svg')); //List of thumbless filetypes
 | ||||||
| 		if(!isset($extArr[$image->ext])){ | 		if(!isset($extArr[$image->ext])){ | ||||||
| 			$tsize = get_thumbnail_size($image->width, $image->height); | 			$tsize = get_thumbnail_size($image->width, $image->height); | ||||||
| 		}else{ | 		}else{ | ||||||
|  | |||||||
| @ -1,17 +1,20 @@ | |||||||
| <?php | <?php | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * A basic chunk of a page |  * Class Block | ||||||
|  |  * | ||||||
|  |  * A basic chunk of a page. | ||||||
|  */ |  */ | ||||||
| class Block { | class Block { | ||||||
| 	/** | 	/** | ||||||
| 	 * The block's title | 	 * The block's title. | ||||||
| 	 * | 	 * | ||||||
| 	 * @var string | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	public $header; | 	public $header; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * The content | 	 * The content of the block. | ||||||
| 	 * | 	 * | ||||||
| 	 * @var string | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| @ -19,7 +22,7 @@ class Block { | |||||||
| 
 | 
 | ||||||
| 	/**  | 	/**  | ||||||
| 	 * Where the block should be placed. The default theme supports | 	 * Where the block should be placed. The default theme supports | ||||||
| 	 * "main" and "left", other themes can add their own areas | 	 * "main" and "left", other themes can add their own areas. | ||||||
| 	 * | 	 * | ||||||
| 	 * @var string | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| @ -35,7 +38,9 @@ class Block { | |||||||
| 	public $position; | 	public $position; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @var int | 	 * A unique ID for the block. | ||||||
|  | 	 * | ||||||
|  | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	public $id; | 	public $id; | ||||||
| 
 | 
 | ||||||
| @ -46,7 +51,7 @@ class Block { | |||||||
| 	 * @param string $body | 	 * @param string $body | ||||||
| 	 * @param string $section | 	 * @param string $section | ||||||
| 	 * @param int $position | 	 * @param int $position | ||||||
| 	 * @param null|int $id | 	 * @param null|int $id A unique ID for the block (generated automatically if null). | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct($header, $body, /*string*/ $section="main", /*int*/ $position=50, $id=null) { | 	public function __construct($header, $body, /*string*/ $section="main", /*int*/ $position=50, $id=null) { | ||||||
| 		$this->header = $header; | 		$this->header = $header; | ||||||
| @ -77,9 +82,12 @@ class Block { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class NavBlock | ||||||
|  |  * | ||||||
|  * A generic navigation block with a link to the main page. |  * A generic navigation block with a link to the main page. | ||||||
|  * |  * | ||||||
|  * Used because "new NavBlock()" is easier than "new Block('Navigation', ..." |  * Used because "new NavBlock()" is easier than "new Block('Navigation', ..." | ||||||
|  |  * | ||||||
|  */ |  */ | ||||||
| class NavBlock extends Block { | class NavBlock extends Block { | ||||||
| 	public function __construct() { | 	public function __construct() { | ||||||
|  | |||||||
| @ -1,94 +1,237 @@ | |||||||
| <?php | <?php | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * an abstract interface for altering a name:value pair list |  * Interface Config | ||||||
|  |  * | ||||||
|  |  * An abstract interface for altering a name:value pair list. | ||||||
|  */ |  */ | ||||||
| interface Config { | interface Config { | ||||||
| 	/** | 	/** | ||||||
| 	 * Save the list of name:value pairs to wherever they came from, | 	 * Save the list of name:value pairs to wherever they came from, | ||||||
| 	 * so that the next time a page is loaded it will use the new | 	 * so that the next time a page is loaded it will use the new | ||||||
| 	 * configuration | 	 * configuration. | ||||||
|  | 	 * | ||||||
|  | 	 * @param null|string $name | ||||||
|  | 	 * @return mixed|void | ||||||
| 	 */ | 	 */ | ||||||
| 	public function save(/*string*/ $name=null); | 	public function save(/*string*/ $name=null); | ||||||
| 
 | 
 | ||||||
| 	/** @name set_* | 	//@{ /*--------------------------------- SET ------------------------------------------------------*/
 | ||||||
| 	 * Set a configuration option to a new value, regardless | 	/** | ||||||
| 	 * of what the value is at the moment | 	 * Set a configuration option to a new value, regardless of what the value is at the moment. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|int $value | ||||||
|  | 	 * @return void | ||||||
| 	 */ | 	 */ | ||||||
| 	//@{
 |  | ||||||
| 	public function set_int(/*string*/ $name, $value); | 	public function set_int(/*string*/ $name, $value); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Set a configuration option to a new value, regardless of what the value is at the moment. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_string(/*string*/ $name, $value); | 	public function set_string(/*string*/ $name, $value); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Set a configuration option to a new value, regardless of what the value is at the moment. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|bool|string $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_bool(/*string*/ $name, $value); | 	public function set_bool(/*string*/ $name, $value); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Set a configuration option to a new value, regardless of what the value is at the moment. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param array $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_array(/*string*/ $name, $value); | 	public function set_array(/*string*/ $name, $value); | ||||||
| 	//@}
 | 	//@} /*--------------------------------------------------------------------------------------------*/
 | ||||||
| 
 | 
 | ||||||
| 	/** @name set_default_* | 	//@{ /*-------------------------------- SET DEFAULT -----------------------------------------------*/
 | ||||||
| 	 * Set a configuration option to a new value, if there is no | 	/** | ||||||
| 	 * value currently. Extensions should generally call these | 	 * Set a configuration option to a new value, if there is no value currently. | ||||||
| 	 * from their InitExtEvent handlers. This has the advantage | 	 * | ||||||
| 	 * that the values will show up in the "advanced" setup page | 	 * Extensions should generally call these from their InitExtEvent handlers. | ||||||
| 	 * where they can be modified, while calling get_* with a | 	 * This has the advantage that the values will show up in the "advanced" setup | ||||||
| 	 * "default" paramater won't show up. | 	 * page where they can be modified, while calling get_* with a "default" | ||||||
|  | 	 * parameter won't show up. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param int $value | ||||||
|  | 	 * @return void | ||||||
| 	 */ | 	 */ | ||||||
| 	//@{
 |  | ||||||
| 	public function set_default_int(/*string*/ $name, $value); | 	public function set_default_int(/*string*/ $name, $value); | ||||||
| 	public function set_default_string(/*string*/ $name, $value); |  | ||||||
| 	public function set_default_bool(/*string*/ $name, $value); |  | ||||||
| 	public function set_default_array(/*string*/ $name, $value); |  | ||||||
| 	//@}
 |  | ||||||
| 
 | 
 | ||||||
| 	/** @name get_* | 	/** | ||||||
| 	 * pick a value out of the table by name, cast to the | 	 * Set a configuration option to a new value, if there is no value currently. | ||||||
| 	 * appropritate data type | 	 * | ||||||
|  | 	 * Extensions should generally call these from their InitExtEvent handlers. | ||||||
|  | 	 * This has the advantage that the values will show up in the "advanced" setup | ||||||
|  | 	 * page where they can be modified, while calling get_* with a "default" | ||||||
|  | 	 * parameter won't show up. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string|null $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
|  | 	public function set_default_string(/*string*/ $name, $value); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Set a configuration option to a new value, if there is no value currently. | ||||||
|  | 	 * | ||||||
|  | 	 * Extensions should generally call these from their InitExtEvent handlers. | ||||||
|  | 	 * This has the advantage that the values will show up in the "advanced" setup | ||||||
|  | 	 * page where they can be modified, while calling get_* with a "default" | ||||||
|  | 	 * parameter won't show up. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param bool|string|null $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
|  | 	public function set_default_bool(/*string*/ $name, $value); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Set a configuration option to a new value, if there is no value currently. | ||||||
|  | 	 * | ||||||
|  | 	 * Extensions should generally call these from their InitExtEvent handlers. | ||||||
|  | 	 * This has the advantage that the values will show up in the "advanced" setup | ||||||
|  | 	 * page where they can be modified, while calling get_* with a "default" | ||||||
|  | 	 * parameter won't show up. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param array $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
|  | 	public function set_default_array(/*string*/ $name, $value); | ||||||
|  | 	//@} /*--------------------------------------------------------------------------------------------*/
 | ||||||
|  | 
 | ||||||
|  | 	//@{ /*--------------------------------- GET ------------------------------------------------------*/
 | ||||||
|  | 	/** | ||||||
|  | 	 * Pick a value out of the table by name, cast to the appropriate data type. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|int $default | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	//@{
 |  | ||||||
| 	public function get_int(/*string*/ $name, $default=null); | 	public function get_int(/*string*/ $name, $default=null); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Pick a value out of the table by name, cast to the appropriate data type. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $default | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function get_string(/*string*/ $name, $default=null); | 	public function get_string(/*string*/ $name, $default=null); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Pick a value out of the table by name, cast to the appropriate data type. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|bool|string $default | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	public function get_bool(/*string*/ $name, $default=null); | 	public function get_bool(/*string*/ $name, $default=null); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Pick a value out of the table by name, cast to the appropriate data type. | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param array|null $default | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_array(/*string*/ $name, $default=array()); | 	public function get_array(/*string*/ $name, $default=array()); | ||||||
| 	//@}
 | 	//@} /*--------------------------------------------------------------------------------------------*/
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class BaseConfig | ||||||
|  |  * | ||||||
|  * Common methods for manipulating the list, loading and saving is |  * Common methods for manipulating the list, loading and saving is | ||||||
|  * left to the concrete implementation |  * left to the concrete implementation | ||||||
|  */ |  */ | ||||||
| abstract class BaseConfig implements Config { | abstract class BaseConfig implements Config { | ||||||
| 	var $values = array(); | 	var $values = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param int|null $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_int(/*string*/ $name, $value) { | 	public function set_int(/*string*/ $name, $value) { | ||||||
| 		$this->values[$name] = parse_shorthand_int($value); | 		$this->values[$name] = parse_shorthand_int($value); | ||||||
| 		$this->save($name); | 		$this->save($name); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_string(/*string*/ $name, $value) { | 	public function set_string(/*string*/ $name, $value) { | ||||||
| 		$this->values[$name] = $value; | 		$this->values[$name] = $value; | ||||||
| 		$this->save($name); | 		$this->save($name); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param bool|null|string $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_bool(/*string*/ $name, $value) { | 	public function set_bool(/*string*/ $name, $value) { | ||||||
| 		$this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N'); | 		$this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N'); | ||||||
| 		$this->save($name); | 		$this->save($name); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param array $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_array(/*string*/ $name, $value) { | 	public function set_array(/*string*/ $name, $value) { | ||||||
| 		assert(isset($value) && is_array($value)); | 		assert(isset($value) && is_array($value)); | ||||||
| 		$this->values[$name] = implode(",", $value); | 		$this->values[$name] = implode(",", $value); | ||||||
| 		$this->save($name); | 		$this->save($name); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param int $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_default_int(/*string*/ $name, $value) { | 	public function set_default_int(/*string*/ $name, $value) { | ||||||
| 		if(is_null($this->get($name))) { | 		if(is_null($this->get($name))) { | ||||||
| 			$this->values[$name] = parse_shorthand_int($value); | 			$this->values[$name] = parse_shorthand_int($value); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_default_string(/*string*/ $name, $value) { | 	public function set_default_string(/*string*/ $name, $value) { | ||||||
| 		if(is_null($this->get($name))) { | 		if(is_null($this->get($name))) { | ||||||
| 			$this->values[$name] = $value; | 			$this->values[$name] = $value; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param bool|null|string $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_default_bool(/*string*/ $name, $value) { | 	public function set_default_bool(/*string*/ $name, $value) { | ||||||
| 		if(is_null($this->get($name))) { | 		if(is_null($this->get($name))) { | ||||||
| 			$this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N'); | 			$this->values[$name] = (($value == 'on' || $value === true) ? 'Y' : 'N'); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param array $value | ||||||
|  | 	 * @return void | ||||||
|  | 	 */ | ||||||
| 	public function set_default_array(/*string*/ $name, $value) { | 	public function set_default_array(/*string*/ $name, $value) { | ||||||
| 		assert(isset($value) && is_array($value)); | 		assert(isset($value) && is_array($value)); | ||||||
| 		if(is_null($this->get($name))) { | 		if(is_null($this->get($name))) { | ||||||
| @ -96,19 +239,47 @@ abstract class BaseConfig implements Config { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|int $default | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	public function get_int(/*string*/ $name, $default=null) { | 	public function get_int(/*string*/ $name, $default=null) { | ||||||
| 		return (int)($this->get($name, $default)); | 		return (int)($this->get($name, $default)); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $default | ||||||
|  | 	 * @return null|string | ||||||
|  | 	 */ | ||||||
| 	public function get_string(/*string*/ $name, $default=null) { | 	public function get_string(/*string*/ $name, $default=null) { | ||||||
| 		return $this->get($name, $default); | 		return $this->get($name, $default); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|bool|string $default | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	public function get_bool(/*string*/ $name, $default=null) { | 	public function get_bool(/*string*/ $name, $default=null) { | ||||||
| 		return bool_escape($this->get($name, $default)); | 		return bool_escape($this->get($name, $default)); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param array $default | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_array(/*string*/ $name, $default=array()) { | 	public function get_array(/*string*/ $name, $default=array()) { | ||||||
| 		return explode(",", $this->get($name, "")); | 		return explode(",", $this->get($name, "")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|mixed $default | ||||||
|  | 	 * @return null|mixed | ||||||
|  | 	 */ | ||||||
| 	private function get(/*string*/ $name, $default=null) { | 	private function get(/*string*/ $name, $default=null) { | ||||||
| 		if(isset($this->values[$name])) { | 		if(isset($this->values[$name])) { | ||||||
| 			return $this->values[$name]; | 			return $this->values[$name]; | ||||||
| @ -121,13 +292,19 @@ abstract class BaseConfig implements Config { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * For testing, mostly |  * Class HardcodeConfig | ||||||
|  |  * | ||||||
|  |  * For testing, mostly. | ||||||
|  */ |  */ | ||||||
| class HardcodeConfig extends BaseConfig { | class HardcodeConfig extends BaseConfig { | ||||||
| 	public function __construct($dict) { | 	public function __construct($dict) { | ||||||
| 		$this->values = $dict; | 		$this->values = $dict; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param null|string $name | ||||||
|  | 	 * @return mixed|void | ||||||
|  | 	 */ | ||||||
| 	public function save(/*string*/ $name=null) { | 	public function save(/*string*/ $name=null) { | ||||||
| 		// static config is static
 | 		// static config is static
 | ||||||
| 	} | 	} | ||||||
| @ -135,6 +312,8 @@ class HardcodeConfig extends BaseConfig { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class StaticConfig | ||||||
|  |  * | ||||||
|  * Loads the config list from a PHP file; the file should be in the format: |  * Loads the config list from a PHP file; the file should be in the format: | ||||||
|  * |  * | ||||||
|  *  <?php |  *  <?php | ||||||
| @ -143,6 +322,10 @@ class HardcodeConfig extends BaseConfig { | |||||||
|  *  ?>
 |  *  ?>
 | ||||||
|  */ |  */ | ||||||
| class StaticConfig extends BaseConfig { | class StaticConfig extends BaseConfig { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @throws Exception | ||||||
|  | 	 */ | ||||||
| 	public function __construct($filename) { | 	public function __construct($filename) { | ||||||
| 		if(file_exists($filename)) { | 		if(file_exists($filename)) { | ||||||
| 			require_once $filename; | 			require_once $filename; | ||||||
| @ -158,6 +341,10 @@ class StaticConfig extends BaseConfig { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param null|string $name | ||||||
|  | 	 * @return mixed|void | ||||||
|  | 	 */ | ||||||
| 	public function save(/*string*/ $name=null) { | 	public function save(/*string*/ $name=null) { | ||||||
| 		// static config is static
 | 		// static config is static
 | ||||||
| 	} | 	} | ||||||
| @ -165,6 +352,8 @@ class StaticConfig extends BaseConfig { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class DatabaseConfig | ||||||
|  |  * | ||||||
|  * Loads the config list from a table in a given database, the table should |  * Loads the config list from a table in a given database, the table should | ||||||
|  * be called config and have the schema: |  * be called config and have the schema: | ||||||
|  * |  * | ||||||
| @ -176,10 +365,13 @@ class StaticConfig extends BaseConfig { | |||||||
|  * \endcode |  * \endcode | ||||||
|  */ |  */ | ||||||
| class DatabaseConfig extends BaseConfig { | class DatabaseConfig extends BaseConfig { | ||||||
|  | 	/** @var \Database|null  */ | ||||||
| 	var $database = null; | 	var $database = null; | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * Load the config table from a database | 	 * Load the config table from a database. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Database $database | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct(Database $database) { | 	public function __construct(Database $database) { | ||||||
| 		$this->database = $database; | 		$this->database = $database; | ||||||
| @ -197,8 +389,11 @@ class DatabaseConfig extends BaseConfig { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * Save the current values as the new config table | 	 * Save the current values as the new config table. | ||||||
|  | 	 * | ||||||
|  | 	 * @param null|string $name | ||||||
|  | 	 * @return mixed|void | ||||||
| 	 */ | 	 */ | ||||||
| 	public function save(/*string*/ $name=null) { | 	public function save(/*string*/ $name=null) { | ||||||
| 		if(is_null($name)) { | 		if(is_null($name)) { | ||||||
| @ -217,7 +412,13 @@ class DatabaseConfig extends BaseConfig { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Class MockConfig | ||||||
|  |  */ | ||||||
| class MockConfig extends HardcodeConfig { | class MockConfig extends HardcodeConfig { | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $config | ||||||
|  | 	 */ | ||||||
| 	public function __construct($config=array()) { | 	public function __construct($config=array()) { | ||||||
| 		$config["db_version"] = "999"; | 		$config["db_version"] = "999"; | ||||||
| 		$config["anon_id"] = "0"; | 		$config["anon_id"] = "0"; | ||||||
|  | |||||||
| @ -2,41 +2,70 @@ | |||||||
| /** @privatesection */ | /** @privatesection */ | ||||||
| // Querylet {{{
 | // Querylet {{{
 | ||||||
| class Querylet { | class Querylet { | ||||||
| 	var $sql; | 	/** @var string */ | ||||||
| 	var $variables; | 	public $sql; | ||||||
|  | 	/** @var array */ | ||||||
|  | 	public $variables; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $sql | ||||||
|  | 	 * @param array $variables | ||||||
|  | 	 */ | ||||||
| 	public function __construct($sql, $variables=array()) { | 	public function __construct($sql, $variables=array()) { | ||||||
| 		$this->sql = $sql; | 		$this->sql = $sql; | ||||||
| 		$this->variables = $variables; | 		$this->variables = $variables; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \Querylet $querylet | ||||||
|  | 	 */ | ||||||
| 	public function append($querylet) { | 	public function append($querylet) { | ||||||
| 		assert(!is_null($querylet)); | 		assert(!is_null($querylet)); | ||||||
| 		$this->sql .= $querylet->sql; | 		$this->sql .= $querylet->sql; | ||||||
| 		$this->variables = array_merge($this->variables, $querylet->variables); | 		$this->variables = array_merge($this->variables, $querylet->variables); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $sql | ||||||
|  | 	 */ | ||||||
| 	public function append_sql($sql) { | 	public function append_sql($sql) { | ||||||
| 		$this->sql .= $sql; | 		$this->sql .= $sql; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param mixed $var | ||||||
|  | 	 */ | ||||||
| 	public function add_variable($var) { | 	public function add_variable($var) { | ||||||
| 		$this->variables[] = $var; | 		$this->variables[] = $var; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| class TagQuerylet { |  | ||||||
| 	var $tag; |  | ||||||
| 	var $positive; |  | ||||||
| 
 | 
 | ||||||
|  | class TagQuerylet { | ||||||
|  | 	/** @var string  */ | ||||||
|  | 	public $tag; | ||||||
|  | 	/** @var bool  */ | ||||||
|  | 	public $positive; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @param bool $positive | ||||||
|  | 	 */ | ||||||
| 	public function __construct($tag, $positive) { | 	public function __construct($tag, $positive) { | ||||||
| 		$this->tag = $tag; | 		$this->tag = $tag; | ||||||
| 		$this->positive = $positive; | 		$this->positive = $positive; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| class ImgQuerylet { |  | ||||||
| 	var $qlet; |  | ||||||
| 	var $positive; |  | ||||||
| 
 | 
 | ||||||
|  | class ImgQuerylet { | ||||||
|  | 	/** @var \Querylet */ | ||||||
|  | 	public $qlet; | ||||||
|  | 	/** @var bool */ | ||||||
|  | 	public $positive; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \Querylet $qlet | ||||||
|  | 	 * @param bool $positive | ||||||
|  | 	 */ | ||||||
| 	public function __construct($qlet, $positive) { | 	public function __construct($qlet, $positive) { | ||||||
| 		$this->qlet = $qlet; | 		$this->qlet = $qlet; | ||||||
| 		$this->positive = $positive; | 		$this->positive = $positive; | ||||||
| @ -45,25 +74,46 @@ class ImgQuerylet { | |||||||
| // }}}
 | // }}}
 | ||||||
| // {{{ db engines
 | // {{{ db engines
 | ||||||
| class DBEngine { | class DBEngine { | ||||||
|  | 	/** @var null|string */ | ||||||
| 	public $name = null; | 	public $name = null; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \PDO $db | ||||||
|  | 	 */ | ||||||
| 	public function init($db) {} | 	public function init($db) {} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $scoreql | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function scoreql_to_sql($scoreql) { | 	public function scoreql_to_sql($scoreql) { | ||||||
| 		return $scoreql; | 		return $scoreql; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function create_table_sql($name, $data) { | 	public function create_table_sql($name, $data) { | ||||||
| 		return 'CREATE TABLE '.$name.' ('.$data.')'; | 		return 'CREATE TABLE '.$name.' ('.$data.')'; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| class MySQL extends DBEngine { | class MySQL extends DBEngine { | ||||||
|  | 	/** @var string */ | ||||||
| 	public $name = "mysql"; | 	public $name = "mysql"; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \PDO $db | ||||||
|  | 	 */ | ||||||
| 	public function init($db) { | 	public function init($db) { | ||||||
| 		$db->exec("SET NAMES utf8;"); | 		$db->exec("SET NAMES utf8;"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function scoreql_to_sql($data) { | 	public function scoreql_to_sql($data) { | ||||||
| 		$data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY auto_increment", $data); | 		$data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY auto_increment", $data); | ||||||
| 		$data = str_replace("SCORE_INET", "VARCHAR(45)", $data); | 		$data = str_replace("SCORE_INET", "VARCHAR(45)", $data); | ||||||
| @ -77,6 +127,11 @@ class MySQL extends DBEngine { | |||||||
| 		return $data; | 		return $data; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function create_table_sql($name, $data) { | 	public function create_table_sql($name, $data) { | ||||||
| 		$data = $this->scoreql_to_sql($data); | 		$data = $this->scoreql_to_sql($data); | ||||||
| 		$ctes = "ENGINE=InnoDB DEFAULT CHARSET='utf8'"; | 		$ctes = "ENGINE=InnoDB DEFAULT CHARSET='utf8'"; | ||||||
| @ -84,12 +139,20 @@ class MySQL extends DBEngine { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| class PostgreSQL extends DBEngine { | class PostgreSQL extends DBEngine { | ||||||
|  | 	/** @var string */ | ||||||
| 	public $name = "pgsql"; | 	public $name = "pgsql"; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \PDO $db | ||||||
|  | 	 */ | ||||||
| 	public function init($db) { | 	public function init($db) { | ||||||
| 		$db->exec("SET application_name TO 'shimmie [{$_SERVER['REMOTE_ADDR']}]';"); | 		$db->exec("SET application_name TO 'shimmie [{$_SERVER['REMOTE_ADDR']}]';"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function scoreql_to_sql($data) { | 	public function scoreql_to_sql($data) { | ||||||
| 		$data = str_replace("SCORE_AIPK", "SERIAL PRIMARY KEY", $data); | 		$data = str_replace("SCORE_AIPK", "SERIAL PRIMARY KEY", $data); | ||||||
| 		$data = str_replace("SCORE_INET", "INET", $data); | 		$data = str_replace("SCORE_INET", "INET", $data); | ||||||
| @ -103,6 +166,11 @@ class PostgreSQL extends DBEngine { | |||||||
| 		return $data; | 		return $data; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function create_table_sql($name, $data) { | 	public function create_table_sql($name, $data) { | ||||||
| 		$data = $this->scoreql_to_sql($data); | 		$data = $this->scoreql_to_sql($data); | ||||||
| 		return 'CREATE TABLE '.$name.' ('.$data.')'; | 		return 'CREATE TABLE '.$name.' ('.$data.')'; | ||||||
| @ -123,8 +191,12 @@ function _concat($a, $b) { return $a . $b; } | |||||||
| function _lower($a) { return strtolower($a); } | function _lower($a) { return strtolower($a); } | ||||||
| 
 | 
 | ||||||
| class SQLite extends DBEngine { | class SQLite extends DBEngine { | ||||||
|  | 	/** @var string  */ | ||||||
| 	public $name = "sqlite"; | 	public $name = "sqlite"; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \PDO $db | ||||||
|  | 	 */ | ||||||
| 	public function init($db) { | 	public function init($db) { | ||||||
| 		ini_set('sqlite.assoc_case', 0); | 		ini_set('sqlite.assoc_case', 0); | ||||||
| 		$db->exec("PRAGMA foreign_keys = ON;"); | 		$db->exec("PRAGMA foreign_keys = ON;"); | ||||||
| @ -138,6 +210,10 @@ class SQLite extends DBEngine { | |||||||
| 		$db->sqliteCreateFunction('lower', '_lower', 1); | 		$db->sqliteCreateFunction('lower', '_lower', 1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function scoreql_to_sql($data) { | 	public function scoreql_to_sql($data) { | ||||||
| 		$data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY", $data); | 		$data = str_replace("SCORE_AIPK", "INTEGER PRIMARY KEY", $data); | ||||||
| 		$data = str_replace("SCORE_INET", "VARCHAR(45)", $data); | 		$data = str_replace("SCORE_INET", "VARCHAR(45)", $data); | ||||||
| @ -150,6 +226,11 @@ class SQLite extends DBEngine { | |||||||
| 		return $data; | 		return $data; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $data | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function create_table_sql($name, $data) { | 	public function create_table_sql($name, $data) { | ||||||
| 		$data = $this->scoreql_to_sql($data); | 		$data = $this->scoreql_to_sql($data); | ||||||
| 		$cols = array(); | 		$cols = array(); | ||||||
| @ -187,22 +268,38 @@ class NoCache implements CacheEngine { | |||||||
| 	public function get_misses() {return 0;} | 	public function get_misses() {return 0;} | ||||||
| } | } | ||||||
| class MemcacheCache implements CacheEngine { | class MemcacheCache implements CacheEngine { | ||||||
| 	var $memcache=null, $hits=0, $misses=0; | 	/** @var \Memcache|null */ | ||||||
|  | 	public $memcache=null; | ||||||
|  | 	/** @var int */ | ||||||
|  | 	private $hits=0; | ||||||
|  | 	/** @var int */ | ||||||
|  | 	private $misses=0; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $args | ||||||
|  | 	 */ | ||||||
| 	public function __construct($args) { | 	public function __construct($args) { | ||||||
| 		$hp = explode(":", $args); | 		$hp = explode(":", $args); | ||||||
| 		if(class_exists("Memcache")) { | 		if(class_exists("Memcache")) { | ||||||
| 			$this->memcache = new Memcache; | 			$this->memcache = new Memcache; | ||||||
| 			@$this->memcache->pconnect($hp[0], $hp[1]); | 			@$this->memcache->pconnect($hp[0], $hp[1]); | ||||||
| 		} | 		} | ||||||
|  | 		else { | ||||||
|  | 			print "no memcache"; exit; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $key | ||||||
|  | 	 * @return array|bool|string | ||||||
|  | 	 */ | ||||||
| 	public function get($key) { | 	public function get($key) { | ||||||
| 		assert(!is_null($key)); | 		assert(!is_null($key)); | ||||||
| 		if((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { |  | ||||||
| 			file_put_contents("data/cache.log", "Cache lookup: $key\n", FILE_APPEND); |  | ||||||
| 		} |  | ||||||
| 		$val = $this->memcache->get($key); | 		$val = $this->memcache->get($key); | ||||||
|  | 		if((DEBUG_CACHE === true) || (is_null(DEBUG_CACHE) && @$_GET['DEBUG_CACHE'])) { | ||||||
|  | 			$hit = $val === false ? "miss" : "hit"; | ||||||
|  | 			file_put_contents("data/cache.log", "Cache $hit: $key\n", FILE_APPEND); | ||||||
|  | 		} | ||||||
| 		if($val !== false) { | 		if($val !== false) { | ||||||
| 			$this->hits++; | 			$this->hits++; | ||||||
| 			return $val; | 			return $val; | ||||||
| @ -213,19 +310,35 @@ class MemcacheCache implements CacheEngine { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $key | ||||||
|  | 	 * @param mixed $val | ||||||
|  | 	 * @param int $time | ||||||
|  | 	 */ | ||||||
| 	public function set($key, $val, $time=0) { | 	public function set($key, $val, $time=0) { | ||||||
| 		assert(!is_null($key)); | 		assert(!is_null($key)); | ||||||
| 		$this->memcache->set($key, $val, false, $time); | 		$this->memcache->set($key, $val, false, $time); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $key | ||||||
|  | 	 */ | ||||||
| 	public function delete($key) { | 	public function delete($key) { | ||||||
| 		assert(!is_null($key)); | 		assert(!is_null($key)); | ||||||
| 		$this->memcache->delete($key); | 		$this->memcache->delete($key); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	public function get_hits() {return $this->hits;} | 	public function get_hits() {return $this->hits;} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	public function get_misses() {return $this->misses;} | 	public function get_misses() {return $this->misses;} | ||||||
| } | } | ||||||
|  | 
 | ||||||
| class APCCache implements CacheEngine { | class APCCache implements CacheEngine { | ||||||
| 	var $hits=0, $misses=0; | 	var $hits=0, $misses=0; | ||||||
| 
 | 
 | ||||||
| @ -267,25 +380,29 @@ class APCCache implements CacheEngine { | |||||||
|  */ |  */ | ||||||
| class Database { | class Database { | ||||||
| 	/** | 	/** | ||||||
| 	 * The PDO database connection object, for anyone who wants direct access | 	 * The PDO database connection object, for anyone who wants direct access. | ||||||
|  | 	 * @var null|PDO | ||||||
| 	 */ | 	 */ | ||||||
| 	private $db = null; | 	private $db = null; | ||||||
|  | 	public $dbtime = 0.0; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Meta info about the database engine | 	 * Meta info about the database engine. | ||||||
| 	 * @var DBEngine | 	 * @var DBEngine|null | ||||||
| 	 */ | 	 */ | ||||||
| 	private $engine = null; | 	private $engine = null; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * The currently active cache engine | 	 * The currently active cache engine. | ||||||
| 	 * @var CacheEngine | 	 * @var CacheEngine|null | ||||||
| 	 */ | 	 */ | ||||||
| 	public $cache = null; | 	public $cache = null; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * A boolean flag to track if we already have an active transaction. | 	 * A boolean flag to track if we already have an active transaction. | ||||||
| 	 * (ie: True if beginTransaction() already called) | 	 * (ie: True if beginTransaction() already called) | ||||||
|  | 	 * | ||||||
|  | 	 * @var bool | ||||||
| 	 */ | 	 */ | ||||||
| 	public $transaction = false; | 	public $transaction = false; | ||||||
| 
 | 
 | ||||||
| @ -364,6 +481,10 @@ class Database { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return bool | ||||||
|  | 	 * @throws SCoreException | ||||||
|  | 	 */ | ||||||
| 	public function commit() { | 	public function commit() { | ||||||
| 		if(!is_null($this->db)) { | 		if(!is_null($this->db)) { | ||||||
| 			if ($this->transaction === true) { | 			if ($this->transaction === true) { | ||||||
| @ -376,6 +497,10 @@ class Database { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return bool | ||||||
|  | 	 * @throws SCoreException | ||||||
|  | 	 */ | ||||||
| 	public function rollback() { | 	public function rollback() { | ||||||
| 		if(!is_null($this->db)) { | 		if(!is_null($this->db)) { | ||||||
| 			if ($this->transaction === true) { | 			if ($this->transaction === true) { | ||||||
| @ -388,23 +513,39 @@ class Database { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $input | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function escape($input) { | 	public function escape($input) { | ||||||
| 		if(is_null($this->db)) $this->connect_db(); | 		if(is_null($this->db)) $this->connect_db(); | ||||||
| 		return $this->db->Quote($input); | 		return $this->db->Quote($input); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $input | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function scoreql_to_sql($input) { | 	public function scoreql_to_sql($input) { | ||||||
| 		if(is_null($this->engine)) $this->connect_engine(); | 		if(is_null($this->engine)) $this->connect_engine(); | ||||||
| 		return $this->engine->scoreql_to_sql($input); | 		return $this->engine->scoreql_to_sql($input); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return null|string | ||||||
|  | 	 */ | ||||||
| 	public function get_driver_name() { | 	public function get_driver_name() { | ||||||
| 		if(is_null($this->engine)) $this->connect_engine(); | 		if(is_null($this->engine)) $this->connect_engine(); | ||||||
| 		return $this->engine->name; | 		return $this->engine->name; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Execute an SQL query and return an PDO resultset | 	 * Execute an SQL query and return an PDO result-set. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return PDOStatement | ||||||
|  | 	 * @throws SCoreException | ||||||
| 	 */ | 	 */ | ||||||
| 	public function execute($query, $args=array()) { | 	public function execute($query, $args=array()) { | ||||||
| 		try { | 		try { | ||||||
| @ -433,54 +574,88 @@ class Database { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Execute an SQL query and return a 2D array | 	 * Execute an SQL query and return a 2D array. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_all($query, $args=array()) { | 	public function get_all($query, $args=array()) { | ||||||
| 		return $this->execute($query, $args)->fetchAll(); | 		$_start = microtime(true); | ||||||
|  | 		$data = $this->execute($query, $args)->fetchAll(); | ||||||
|  | 		$this->dbtime += microtime(true) - $_start; | ||||||
|  | 		return $data; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Execute an SQL query and return a single row | 	 * Execute an SQL query and return a single row. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return mixed|null | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_row($query, $args=array()) { | 	public function get_row($query, $args=array()) { | ||||||
|  | 		$_start = microtime(true); | ||||||
| 		$row = $this->execute($query, $args)->fetch(); | 		$row = $this->execute($query, $args)->fetch(); | ||||||
|  | 		$this->dbtime += microtime(true) - $_start; | ||||||
| 		return $row ? $row : null; | 		return $row ? $row : null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Execute an SQL query and return the first column of each row | 	 * Execute an SQL query and return the first column of each row. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_col($query, $args=array()) { | 	public function get_col($query, $args=array()) { | ||||||
|  | 		$_start = microtime(true); | ||||||
| 		$stmt = $this->execute($query, $args); | 		$stmt = $this->execute($query, $args); | ||||||
| 		$res = array(); | 		$res = array(); | ||||||
| 		foreach($stmt as $row) { | 		foreach($stmt as $row) { | ||||||
| 			$res[] = $row[0]; | 			$res[] = $row[0]; | ||||||
| 		} | 		} | ||||||
|  | 		$this->dbtime += microtime(true) - $_start; | ||||||
| 		return $res; | 		return $res; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Execute an SQL query and return the the first row => the second rown | 	 * Execute an SQL query and return the the first row => the second rown. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_pairs($query, $args=array()) { | 	public function get_pairs($query, $args=array()) { | ||||||
|  | 		$_start = microtime(true); | ||||||
| 		$stmt = $this->execute($query, $args); | 		$stmt = $this->execute($query, $args); | ||||||
| 		$res = array(); | 		$res = array(); | ||||||
| 		foreach($stmt as $row) { | 		foreach($stmt as $row) { | ||||||
| 			$res[$row[0]] = $row[1]; | 			$res[$row[0]] = $row[1]; | ||||||
| 		} | 		} | ||||||
|  | 		$this->dbtime += microtime(true) - $_start; | ||||||
| 		return $res; | 		return $res; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Execute an SQL query and return a single value | 	 * Execute an SQL query and return a single value. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return mixed | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_one($query, $args=array()) { | 	public function get_one($query, $args=array()) { | ||||||
|  | 		$_start = microtime(true); | ||||||
| 		$row = $this->execute($query, $args)->fetch(); | 		$row = $this->execute($query, $args)->fetch(); | ||||||
|  | 		$this->dbtime += microtime(true) - $_start; | ||||||
| 		return $row[0]; | 		return $row[0]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * get the ID of the last inserted row | 	 * Get the ID of the last inserted row. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string|null $seq | ||||||
|  | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_last_insert_id($seq) { | 	public function get_last_insert_id($seq) { | ||||||
| 		if($this->engine->name == "pgsql") { | 		if($this->engine->name == "pgsql") { | ||||||
| @ -492,15 +667,20 @@ class Database { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Create a table from pseudo-SQL | 	 * Create a table from pseudo-SQL. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $data | ||||||
| 	 */ | 	 */ | ||||||
| 	public function create_table($name, $data) { | 	public function create_table($name, $data) { | ||||||
| 		if(is_null($this->engine)) $this->connect_engine(); | 		if(is_null($this->engine)) { $this->connect_engine(); } | ||||||
| 		$this->execute($this->engine->create_table_sql($name, $data)); | 		$this->execute($this->engine->create_table_sql($name, $data)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the number of tables present in the current database. | 	 * Returns the number of tables present in the current database. | ||||||
|  | 	 * | ||||||
|  | 	 * @return int|null | ||||||
| 	 */ | 	 */ | ||||||
| 	public function count_tables() { | 	public function count_tables() { | ||||||
| 		if(is_null($this->db) || is_null($this->engine)) $this->connect_db(); | 		if(is_null($this->db) || is_null($this->engine)) $this->connect_db(); | ||||||
| @ -525,14 +705,26 @@ class Database { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class MockDatabase extends Database { | class MockDatabase extends Database { | ||||||
|  | 	/** @var int */ | ||||||
| 	var $query_id = 0; | 	var $query_id = 0; | ||||||
|  | 	/** @var array */ | ||||||
| 	var $responses = array(); | 	var $responses = array(); | ||||||
|  | 	/** @var \NoCache|null  */ | ||||||
| 	var $cache = null; | 	var $cache = null; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $responses | ||||||
|  | 	 */ | ||||||
| 	public function __construct($responses = array()) { | 	public function __construct($responses = array()) { | ||||||
| 		$this->cache = new NoCache(); | 		$this->cache = new NoCache(); | ||||||
| 		$this->responses = $responses; | 		$this->responses = $responses; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $params | ||||||
|  | 	 * @return PDOStatement | ||||||
|  | 	 */ | ||||||
| 	public function execute($query, $params=array()) { | 	public function execute($query, $params=array()) { | ||||||
| 		log_debug("mock-database", | 		log_debug("mock-database", | ||||||
| 			"QUERY: " . $query . | 			"QUERY: " . $query . | ||||||
| @ -542,13 +734,51 @@ class MockDatabase extends Database { | |||||||
| 		return $this->responses[$this->query_id++]; | 		return $this->responses[$this->query_id++]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return array|PDOStatement | ||||||
|  | 	 */ | ||||||
| 	public function get_all($query, $args=array()) {return $this->execute($query, $args);} | 	public function get_all($query, $args=array()) {return $this->execute($query, $args);} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return mixed|null|PDOStatement | ||||||
|  | 	 */ | ||||||
| 	public function get_row($query, $args=array()) {return $this->execute($query, $args);} | 	public function get_row($query, $args=array()) {return $this->execute($query, $args);} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return array|PDOStatement | ||||||
|  | 	 */ | ||||||
| 	public function get_col($query, $args=array()) {return $this->execute($query, $args);} | 	public function get_col($query, $args=array()) {return $this->execute($query, $args);} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return array|PDOStatement | ||||||
|  | 	 */ | ||||||
| 	public function get_pairs($query, $args=array()) {return $this->execute($query, $args);} | 	public function get_pairs($query, $args=array()) {return $this->execute($query, $args);} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $query | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 * @return mixed|PDOStatement | ||||||
|  | 	 */ | ||||||
| 	public function get_one($query, $args=array()) {return $this->execute($query, $args);} | 	public function get_one($query, $args=array()) {return $this->execute($query, $args);} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param null|string $seq | ||||||
|  | 	 * @return int|string | ||||||
|  | 	 */ | ||||||
| 	public function get_last_insert_id($seq) {return $this->query_id;} | 	public function get_last_insert_id($seq) {return $this->query_id;} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $sql | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function scoreql_to_sql($sql) {return $sql;} | 	public function scoreql_to_sql($sql) {return $sql;} | ||||||
| 	public function create_table($name, $def) {} | 	public function create_table($name, $def) {} | ||||||
| 	public function connect_engine() {} | 	public function connect_engine() {} | ||||||
|  | |||||||
| @ -1,21 +1,40 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class Email { |  | ||||||
| /** | /** | ||||||
|  |  * Class Email | ||||||
|  |  * | ||||||
|  * A generic email. |  * A generic email. | ||||||
|  */ |  */ | ||||||
|  | class Email { | ||||||
|  | 	/** @var string */ | ||||||
| 	public $to; | 	public $to; | ||||||
|  | 	/** @var string  */ | ||||||
| 	public $subject; | 	public $subject; | ||||||
|  | 	/** @var string  */ | ||||||
| 	public $header; | 	public $header; | ||||||
|  | 	/** @var null|string  */ | ||||||
| 	public $style; | 	public $style; | ||||||
|  | 	/** @var null|string  */ | ||||||
| 	public $header_img; | 	public $header_img; | ||||||
|  | 	/** @var null|string  */ | ||||||
| 	public $sitename; | 	public $sitename; | ||||||
|  | 	/** @var null|string  */ | ||||||
| 	public $sitedomain; | 	public $sitedomain; | ||||||
|  | 	/** @var null|string */ | ||||||
| 	public $siteemail; | 	public $siteemail; | ||||||
|  | 	/** @var string */ | ||||||
| 	public $date; | 	public $date; | ||||||
|  | 	/** @var string */ | ||||||
| 	public $body; | 	public $body; | ||||||
|  | 	/** @var null|string */ | ||||||
| 	public $footer; | 	public $footer; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $to | ||||||
|  | 	 * @param string $subject | ||||||
|  | 	 * @param string $header | ||||||
|  | 	 * @param string $body | ||||||
|  | 	 */ | ||||||
| 	public function __construct($to, $subject, $header, $body) { | 	public function __construct($to, $subject, $header, $body) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$this->to = $to; | 		$this->to = $to; | ||||||
|  | |||||||
| @ -26,8 +26,19 @@ class InitExtEvent extends Event {} | |||||||
|  * $event->get_arg(0) = "42" |  * $event->get_arg(0) = "42" | ||||||
|  */ |  */ | ||||||
| class PageRequestEvent extends Event { | class PageRequestEvent extends Event { | ||||||
|  | 	/** | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
| 	public $args; | 	public $args; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @var int | ||||||
|  | 	 */ | ||||||
| 	public $arg_count; | 	public $arg_count; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @var int | ||||||
|  | 	 */ | ||||||
| 	public $part_count; | 	public $part_count; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -90,7 +101,7 @@ class PageRequestEvent extends Event { | |||||||
| 	 * Get the n th argument of the page request (if it exists.) | 	 * Get the n th argument of the page request (if it exists.) | ||||||
| 	 * | 	 * | ||||||
| 	 * @param int $n | 	 * @param int $n | ||||||
| 	 * @return string|null The argmuent (string) or NULL | 	 * @return string|null The argument (string) or NULL | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_arg(/*int*/ $n) { | 	public function get_arg(/*int*/ $n) { | ||||||
| 		$offset = $this->part_count + $n; | 		$offset = $this->part_count + $n; | ||||||
| @ -154,9 +165,19 @@ class PageRequestEvent extends Event { | |||||||
|  * Sent when index.php is called from the command line |  * Sent when index.php is called from the command line | ||||||
|  */ |  */ | ||||||
| class CommandEvent extends Event { | class CommandEvent extends Event { | ||||||
|  | 	/** | ||||||
|  | 	 * @var string | ||||||
|  | 	 */ | ||||||
| 	public $cmd = "help"; | 	public $cmd = "help"; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
| 	public $args = array(); | 	public $args = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string[] $args | ||||||
|  | 	 */ | ||||||
| 	public function __construct(/*array(string)*/ $args) { | 	public function __construct(/*array(string)*/ $args) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 
 | 
 | ||||||
| @ -215,19 +236,28 @@ class CommandEvent extends Event { | |||||||
| class TextFormattingEvent extends Event { | class TextFormattingEvent extends Event { | ||||||
| 	/** | 	/** | ||||||
| 	 * For reference | 	 * For reference | ||||||
|  | 	 * | ||||||
|  | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	var $original; | 	public $original; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * with formatting applied | 	 * with formatting applied | ||||||
|  | 	 * | ||||||
|  | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	var $formatted; | 	public $formatted; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * with formatting removed | 	 * with formatting removed | ||||||
|  | 	 * | ||||||
|  | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	var $stripped; | 	public $stripped; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 */ | ||||||
| 	public function __construct(/*string*/ $text) { | 	public function __construct(/*string*/ $text) { | ||||||
| 		$h_text = html_escape(trim($text)); | 		$h_text = html_escape(trim($text)); | ||||||
| 		$this->original  = $h_text; | 		$this->original  = $h_text; | ||||||
| @ -244,36 +274,44 @@ class LogEvent extends Event { | |||||||
| 	/** | 	/** | ||||||
| 	 * a category, normally the extension name | 	 * a category, normally the extension name | ||||||
| 	 * | 	 * | ||||||
| 	 * @return string | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	var $section; | 	public $section; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * See python... | 	 * See python... | ||||||
| 	 * | 	 * | ||||||
| 	 * @return int | 	 * @var int | ||||||
| 	 */ | 	 */ | ||||||
| 	var $priority = 0; | 	public $priority = 0; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Free text to be logged | 	 * Free text to be logged | ||||||
| 	 * | 	 * | ||||||
| 	 * @return text | 	 * @var string | ||||||
| 	 */ | 	 */ | ||||||
| 	var $message; | 	public $message; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * The time that the event was created | 	 * The time that the event was created | ||||||
| 	 * | 	 * | ||||||
| 	 * @return int | 	 * @var int | ||||||
| 	 */ | 	 */ | ||||||
| 	var $time; | 	public $time; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Extra data to be held separate | 	 * Extra data to be held separate | ||||||
|  | 	 * | ||||||
|  | 	 * @var array | ||||||
| 	 */ | 	 */ | ||||||
| 	var $args; | 	public $args; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $section | ||||||
|  | 	 * @param int $priority | ||||||
|  | 	 * @param string $message | ||||||
|  | 	 * @param array $args | ||||||
|  | 	 */ | ||||||
| 	public function __construct($section, $priority, $message, $args) { | 	public function __construct($section, $priority, $message, $args) { | ||||||
| 		$this->section = $section; | 		$this->section = $section; | ||||||
| 		$this->priority = $priority; | 		$this->priority = $priority; | ||||||
|  | |||||||
| @ -1,11 +1,16 @@ | |||||||
| <?php | <?php | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * A base exception to be caught by the upper levels |  * Class SCoreException | ||||||
|  |  * | ||||||
|  |  * A base exception to be caught by the upper levels. | ||||||
|  */ |  */ | ||||||
| class SCoreException extends Exception {} | class SCoreException extends Exception {} | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A fairly common, generic exception |  * Class PermissionDeniedException | ||||||
|  |  * | ||||||
|  |  * A fairly common, generic exception. | ||||||
|  */ |  */ | ||||||
| class PermissionDeniedException extends SCoreException {} | class PermissionDeniedException extends SCoreException {} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -70,6 +70,8 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class Extension | ||||||
|  |  * | ||||||
|  * send_event(BlahEvent()) -> onBlah($event) |  * send_event(BlahEvent()) -> onBlah($event) | ||||||
|  * |  * | ||||||
|  * Also loads the theme object into $this->theme if available |  * Also loads the theme object into $this->theme if available | ||||||
| @ -96,7 +98,11 @@ abstract class Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Find the theme object for a given extension | 	 * Find the theme object for a given extension. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Extension $class | ||||||
|  | 	 * @param bool $fatal | ||||||
|  | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_theme_object(Extension $class, $fatal=true) { | 	private function get_theme_object(Extension $class, $fatal=true) { | ||||||
| 		$base = get_class($class); | 		$base = get_class($class); | ||||||
| @ -114,7 +120,9 @@ abstract class Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Override this to change the priority of the extension, | 	 * Override this to change the priority of the extension, | ||||||
| 	 * lower numbered ones will recieve events first | 	 * lower numbered ones will recieve events first. | ||||||
|  | 	 * | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_priority() { | 	public function get_priority() { | ||||||
| 		return 50; | 		return 50; | ||||||
| @ -122,23 +130,43 @@ abstract class Extension { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Several extensions have this in common, make a common API |  * Class FormatterExtension | ||||||
|  |  * | ||||||
|  |  * Several extensions have this in common, make a common API. | ||||||
|  */ |  */ | ||||||
| abstract class FormatterExtension extends Extension { | abstract class FormatterExtension extends Extension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param TextFormattingEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onTextFormatting(TextFormattingEvent $event) { | 	public function onTextFormatting(TextFormattingEvent $event) { | ||||||
| 		$event->formatted = $this->format($event->formatted); | 		$event->formatted = $this->format($event->formatted); | ||||||
| 		$event->stripped  = $this->strip($event->stripped); | 		$event->stripped  = $this->strip($event->stripped); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	abstract public function format(/*string*/ $text); | 	abstract public function format(/*string*/ $text); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	abstract public function strip(/*string*/ $text); | 	abstract public function strip(/*string*/ $text); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class DataHandlerExtension | ||||||
|  |  * | ||||||
|  * This too is a common class of extension with many methods in common, |  * This too is a common class of extension with many methods in common, | ||||||
|  * so we have a base class to extend from |  * so we have a base class to extend from. | ||||||
|  */ |  */ | ||||||
| abstract class DataHandlerExtension extends Extension { | abstract class DataHandlerExtension extends Extension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param DataUploadEvent $event | ||||||
|  | 	 * @throws UploadException | ||||||
|  | 	 */ | ||||||
| 	public function onDataUpload(DataUploadEvent $event) { | 	public function onDataUpload(DataUploadEvent $event) { | ||||||
| 		$supported_ext = $this->supported_ext($event->type); | 		$supported_ext = $this->supported_ext($event->type); | ||||||
| 		$check_contents = $this->check_contents($event->tmpname); | 		$check_contents = $this->check_contents($event->tmpname); | ||||||
| @ -202,6 +230,9 @@ abstract class DataHandlerExtension extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param ThumbnailGenerationEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onThumbnailGeneration(ThumbnailGenerationEvent $event) { | 	public function onThumbnailGeneration(ThumbnailGenerationEvent $event) { | ||||||
| 		if($this->supported_ext($event->type)) { | 		if($this->supported_ext($event->type)) { | ||||||
| 			if (method_exists($this, 'create_thumb_force') && $event->force == true) { | 			if (method_exists($this, 'create_thumb_force') && $event->force == true) { | ||||||
| @ -213,6 +244,9 @@ abstract class DataHandlerExtension extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param DisplayingImageEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onDisplayingImage(DisplayingImageEvent $event) { | 	public function onDisplayingImage(DisplayingImageEvent $event) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 		if($this->supported_ext($event->image->ext)) { | 		if($this->supported_ext($event->image->ext)) { | ||||||
| @ -229,9 +263,29 @@ abstract class DataHandlerExtension extends Extension { | |||||||
| 	protected function setup() {} | 	protected function setup() {} | ||||||
| 	*/ | 	*/ | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	abstract protected function supported_ext($ext); | 	abstract protected function supported_ext($ext); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $tmpname | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	abstract protected function check_contents($tmpname); | 	abstract protected function check_contents($tmpname); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @param array $metadata | ||||||
|  | 	 * @return Image|null | ||||||
|  | 	 */ | ||||||
| 	abstract protected function create_image_from_data($filename, $metadata); | 	abstract protected function create_image_from_data($filename, $metadata); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	abstract protected function create_thumb($hash); | 	abstract protected function create_thumb($hash); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -31,15 +31,38 @@ $order_sql = null; // this feels ugly | |||||||
| require_once "lib/flexihash.php"; | require_once "lib/flexihash.php"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * An object representing an entry in the images table. As of 2.2, this no |  * Class Image | ||||||
|  * longer necessarily represents an image per se, but could be a video, |  * | ||||||
|  * sound file, or any other supported upload type. |  * An object representing an entry in the images table. | ||||||
|  |  * | ||||||
|  |  * As of 2.2, this no longer necessarily represents an | ||||||
|  |  * image per se, but could be a video, sound file, or any | ||||||
|  |  * other supported upload type. | ||||||
|  */ |  */ | ||||||
| class Image { | class Image { | ||||||
|  | 	/** @var null|int */ | ||||||
| 	public $id = null; | 	public $id = null; | ||||||
| 	public $height, $width; | 
 | ||||||
| 	public $hash, $filesize; | 	/** @var int */ | ||||||
| 	public $filename, $ext; | 	public $height; | ||||||
|  | 
 | ||||||
|  | 	/** @var int */ | ||||||
|  | 	public $width; | ||||||
|  | 
 | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $hash; | ||||||
|  | 
 | ||||||
|  | 	public $filesize; | ||||||
|  | 
 | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $filename; | ||||||
|  | 
 | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $ext; | ||||||
|  | 
 | ||||||
|  | 	/** @var string[]|null */ | ||||||
|  | 	public $tag_array; | ||||||
|  | 
 | ||||||
| 	public $owner_id, $owner_ip; | 	public $owner_id, $owner_ip; | ||||||
| 	public $posted, $posted_timestamp; | 	public $posted, $posted_timestamp; | ||||||
| 	public $source; | 	public $source; | ||||||
| @ -47,7 +70,9 @@ class Image { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * One will very rarely construct an image directly, more common | 	 * One will very rarely construct an image directly, more common | ||||||
| 	 * would be to use Image::by_id, Image::by_hash, etc | 	 * would be to use Image::by_id, Image::by_hash, etc. | ||||||
|  | 	 * | ||||||
|  | 	 * @param null|mixed $row | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct($row=null) { | 	public function __construct($row=null) { | ||||||
| 		if(!is_null($row)) { | 		if(!is_null($row)) { | ||||||
| @ -66,7 +91,7 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Find an image by ID | 	 * Find an image by ID. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param int $id | 	 * @param int $id | ||||||
| 	 * @return Image | 	 * @return Image | ||||||
| @ -79,7 +104,7 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Find an image by hash | 	 * Find an image by hash. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param string $hash | 	 * @param string $hash | ||||||
| 	 * @return Image | 	 * @return Image | ||||||
| @ -92,9 +117,9 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Pick a random image out of a set | 	 * Pick a random image out of a set. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $tags | 	 * @param string[] $tags | ||||||
| 	 * @return Image | 	 * @return Image | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function by_random($tags=array()) { | 	public static function by_random($tags=array()) { | ||||||
| @ -112,9 +137,9 @@ class Image { | |||||||
| 	 * | 	 * | ||||||
| 	 * @param int $start | 	 * @param int $start | ||||||
| 	 * @param int $limit | 	 * @param int $limit | ||||||
| 	 * @param array $tags | 	 * @param string[] $tags | ||||||
| 	 * @throws SCoreException | 	 * @throws SCoreException | ||||||
| 	 * @return Array | 	 * @return Image[] | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function find_images(/*int*/ $start, /*int*/ $limit, $tags=array()) { | 	public static function find_images(/*int*/ $start, /*int*/ $limit, $tags=array()) { | ||||||
| 		assert(is_numeric($start)); | 		assert(is_numeric($start)); | ||||||
| @ -153,7 +178,7 @@ class Image { | |||||||
| 	/** | 	/** | ||||||
| 	 * Count the number of image results for a given search | 	 * Count the number of image results for a given search | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $tags | 	 * @param string[] $tags | ||||||
| 	 * @return mixed | 	 * @return mixed | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function count_images($tags=array()) { | 	public static function count_images($tags=array()) { | ||||||
| @ -185,7 +210,7 @@ class Image { | |||||||
| 	/** | 	/** | ||||||
| 	 * Count the number of pages for a given search | 	 * Count the number of pages for a given search | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $tags | 	 * @param string[] $tags | ||||||
| 	 * @return float | 	 * @return float | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function count_pages($tags=array()) { | 	public static function count_pages($tags=array()) { | ||||||
| @ -205,7 +230,7 @@ class Image { | |||||||
| 	 * Rather than simply $this_id + 1, one must take into account | 	 * Rather than simply $this_id + 1, one must take into account | ||||||
| 	 * deleted images and search queries | 	 * deleted images and search queries | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $tags | 	 * @param string[] $tags | ||||||
| 	 * @param bool $next | 	 * @param bool $next | ||||||
| 	 * @return Image | 	 * @return Image | ||||||
| 	 */ | 	 */ | ||||||
| @ -239,7 +264,7 @@ class Image { | |||||||
| 	/** | 	/** | ||||||
| 	 * The reverse of get_next | 	 * The reverse of get_next | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $tags | 	 * @param string[] $tags | ||||||
| 	 * @return Image | 	 * @return Image | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_prev($tags=array()) { | 	public function get_prev($tags=array()) { | ||||||
| @ -269,7 +294,9 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get this image's tags as an array | 	 * Get this image's tags as an array. | ||||||
|  | 	 * | ||||||
|  | 	 * @return string[] | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_tag_array() { | 	public function get_tag_array() { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -349,7 +376,7 @@ class Image { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get the tooltip for this image, formatted according to the | 	 * Get the tooltip for this image, formatted according to the | ||||||
| 	 * configured template | 	 * configured template. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| @ -378,7 +405,7 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Figure out where the full size image is on disk | 	 * Figure out where the full size image is on disk. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| @ -387,7 +414,7 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Figure out where the thumbnail is on disk | 	 * Figure out where the thumbnail is on disk. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| @ -396,7 +423,7 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get the original filename | 	 * Get the original filename. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| @ -405,7 +432,7 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get the image's mime type | 	 * Get the image's mime type. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| @ -480,7 +507,9 @@ class Image { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the tags for this image | 	 * Set the tags for this image. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string[] $tags | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_tags($tags) { | 	public function set_tags($tags) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -505,6 +534,11 @@ class Image { | |||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | 				if(mb_strlen($tag, 'UTF-8') > 255){ | ||||||
|  | 					flash_message("The tag below is longer than 255 characters, please use a shorter tag.\n$tag\n"); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
| 				$id = $database->get_one( | 				$id = $database->get_one( | ||||||
| 						$database->scoreql_to_sql( | 						$database->scoreql_to_sql( | ||||||
| 							"SELECT id FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag)" | 							"SELECT id FROM tags WHERE SCORE_STRNORM(tag) = SCORE_STRNORM(:tag)" | ||||||
| @ -533,7 +567,7 @@ class Image { | |||||||
| 						array("tag"=>$tag)); | 						array("tag"=>$tag)); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			log_info("core_image", "Tags for Image #{$this->id} set to: ".implode(" ", $tags), false, array("image_id" => $this->id)); | 			log_info("core_image", "Tags for Image #{$this->id} set to: ".implode(" ", $tags), null, array("image_id" => $this->id)); | ||||||
| 			$database->cache->delete("image-{$this->id}-tags"); | 			$database->cache->delete("image-{$this->id}-tags"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -564,7 +598,7 @@ class Image { | |||||||
| 	/** | 	/** | ||||||
| 	 * Someone please explain this | 	 * Someone please explain this | ||||||
| 	 * | 	 * | ||||||
| 	 * @param $tmpl | 	 * @param string $tmpl | ||||||
| 	 * @param string $_escape | 	 * @param string $_escape | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| @ -637,6 +671,10 @@ class Image { | |||||||
| 		return $tmpl; | 		return $tmpl; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string[] $terms | ||||||
|  | 	 * @return \Querylet | ||||||
|  | 	 */ | ||||||
| 	private static function build_search_querylet($terms) { | 	private static function build_search_querylet($terms) { | ||||||
| 		assert(is_array($terms)); | 		assert(is_array($terms)); | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -666,6 +704,9 @@ class Image { | |||||||
| 	 *   C) Runs really slow on bad databases: | 	 *   C) Runs really slow on bad databases: | ||||||
| 	 *      All the subqueries are executed every time for every row in the | 	 *      All the subqueries are executed every time for every row in the | ||||||
| 	 *      images table. Yes, MySQL does suck this much. | 	 *      images table. Yes, MySQL does suck this much. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string[] $terms | ||||||
|  | 	 * @return \Querylet | ||||||
| 	 */ | 	 */ | ||||||
| 	private static function build_accurate_search_querylet($terms) { | 	private static function build_accurate_search_querylet($terms) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -932,16 +973,22 @@ class Image { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// more than one positive tag, or more than zero negative tags
 | 		// more than one positive tag, and zero or more negative tags
 | ||||||
| 		else { | 		else if($positive_tag_count >= 1) { | ||||||
| 			$tag_id_array = array(); | 			$tag_id_array = array(); | ||||||
| 			$tags_ok = true; | 			$tags_ok = true; | ||||||
|  | 
 | ||||||
|  | 			$x = 0; | ||||||
| 			foreach($tag_search->variables as $tag) { | 			foreach($tag_search->variables as $tag) { | ||||||
| 				$tag_ids = $database->get_col("SELECT id FROM tags WHERE tag LIKE :tag", array("tag"=>$tag)); | 				$tag_ids = $database->get_col("SELECT id FROM tags WHERE tag LIKE :tag", array("tag"=>$tag)); | ||||||
| 				$tag_id_array = array_merge($tag_id_array, $tag_ids); | 				$tag_id_array = array_merge($tag_id_array, $tag_ids); | ||||||
| 				$tags_ok = count($tag_ids) > 0; | 
 | ||||||
|  | 				$tags_ok = count($tag_ids) > 0 || !$tag_querylets[$x]->positive; | ||||||
| 				if(!$tags_ok) break; | 				if(!$tags_ok) break; | ||||||
|  | 
 | ||||||
|  | 				$x++; | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
| 			if($tags_ok) { | 			if($tags_ok) { | ||||||
| 				$tag_id_list = join(', ', $tag_id_array); | 				$tag_id_list = join(', ', $tag_id_array); | ||||||
| 
 | 
 | ||||||
| @ -977,15 +1024,27 @@ class Image { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		//zero positive tags and one or more negative tags
 | ||||||
|  | 		//TODO: This isn't currently implemented. SEE: https://github.com/shish/shimmie2/issues/66
 | ||||||
|  | 		else{ | ||||||
|  | 			$query = new Querylet(" | ||||||
|  | 				SELECT images.* | ||||||
|  | 				FROM images | ||||||
|  | 				WHERE 1=0 | ||||||
|  | 			");
 | ||||||
|  | 		} | ||||||
| 		$tag_n = 0; | 		$tag_n = 0; | ||||||
| 		return $query; | 		return $query; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class Tag | ||||||
|  |  * | ||||||
|  * A class for organising the tag related functions. |  * A class for organising the tag related functions. | ||||||
|  * |  * | ||||||
|  * All the methods are static, one should never actually use a tag object. |  * All the methods are static, one should never actually use a tag object. | ||||||
|  |  * | ||||||
|  */ |  */ | ||||||
| class Tag { | class Tag { | ||||||
| 	/** | 	/** | ||||||
| @ -1003,7 +1062,11 @@ class Tag { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Turn any string or array into a valid tag array | 	 * Turn any string or array into a valid tag array. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string|string[] $tags | ||||||
|  | 	 * @param bool $tagme | ||||||
|  | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function explode($tags, $tagme=true) { | 	public static function explode($tags, $tagme=true) { | ||||||
| 		assert(is_string($tags) || is_array($tags)); | 		assert(is_string($tags) || is_array($tags)); | ||||||
| @ -1033,7 +1096,7 @@ class Tag { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param $tags | 	 * @param string|string[] $tags | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function implode($tags) { | 	public static function implode($tags) { | ||||||
| @ -1073,6 +1136,10 @@ class Tag { | |||||||
| 		return $negative ? "-$newtag" : $newtag; | 		return $negative ? "-$newtag" : $newtag; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public static function resolve_wildcard($tag) { | 	public static function resolve_wildcard($tag) { | ||||||
| 		// if there is no wildcard, return the tag
 | 		// if there is no wildcard, return the tag
 | ||||||
| 		if(strpos($tag, "*") === false) { | 		if(strpos($tag, "*") === false) { | ||||||
| @ -1102,8 +1169,8 @@ class Tag { | |||||||
| 	/** | 	/** | ||||||
| 	 * This function takes a list (array) of tags and changes any tags that have aliases | 	 * This function takes a list (array) of tags and changes any tags that have aliases | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $tags Array of tags | 	 * @param string[] $tags Array of tags | ||||||
| 	 * @return array of tags | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function resolve_aliases($tags) { | 	public static function resolve_aliases($tags) { | ||||||
| 		assert(is_array($tags)); | 		assert(is_array($tags)); | ||||||
| @ -1139,7 +1206,11 @@ class Tag { | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Move a file from PHP's temporary area into shimmie's image storage |  * Move a file from PHP's temporary area into shimmie's image storage | ||||||
|  * hierarchy, or throw an exception trying |  * hierarchy, or throw an exception trying. | ||||||
|  |  * | ||||||
|  |  * @param DataUploadEvent $event | ||||||
|  |  * @return bool | ||||||
|  |  * @throws UploadException | ||||||
|  */ |  */ | ||||||
| function move_upload_to_archive(DataUploadEvent $event) { | function move_upload_to_archive(DataUploadEvent $event) { | ||||||
| 	$target = warehouse_path("images", $event->hash); | 	$target = warehouse_path("images", $event->hash); | ||||||
|  | |||||||
| @ -28,28 +28,32 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class Page | ||||||
|  |  * | ||||||
|  * A data structure for holding all the bits of data that make up a page. |  * A data structure for holding all the bits of data that make up a page. | ||||||
|  * |  * | ||||||
|  * The various extensions all add whatever they want to this structure, |  * The various extensions all add whatever they want to this structure, | ||||||
|  * then Layout turns it into HTML |  * then Layout turns it into HTML. | ||||||
|  */ |  */ | ||||||
| class Page { | class Page { | ||||||
| 	/** @name Overall */ | 	/** @name Overall */ | ||||||
| 	//@{
 | 	//@{
 | ||||||
| 	/** @private */ | 	/** @var string */ | ||||||
| 	var $mode = "page"; | 	public $mode = "page"; | ||||||
| 	/** @private */ | 	/** @var string */ | ||||||
| 	var $type = "text/html; charset=utf-8"; | 	public $type = "text/html; charset=utf-8"; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set what this page should do; "page", "data", or "redirect". | 	 * Set what this page should do; "page", "data", or "redirect". | ||||||
|  | 	 * @param string $mode | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_mode($mode) { | 	public function set_mode($mode) { | ||||||
| 		$this->mode = $mode; | 		$this->mode = $mode; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the page's MIME type | 	 * Set the page's MIME type. | ||||||
|  | 	 * @param string $type | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_type($type) { | 	public function set_type($type) { | ||||||
| 		$this->type = $type; | 		$this->type = $type; | ||||||
| @ -61,20 +65,23 @@ class Page { | |||||||
| 	/** @name "data" mode */ | 	/** @name "data" mode */ | ||||||
| 	//@{
 | 	//@{
 | ||||||
| 
 | 
 | ||||||
| 	/** @private */ | 	/** @var string */ | ||||||
| 	var $data = ""; | 	private $data = ""; | ||||||
| 	/** @private */ | 
 | ||||||
| 	var $filename = null; | 	/** @var string */ | ||||||
|  | 	private $filename = null; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the raw data to be sent | 	 * Set the raw data to be sent. | ||||||
|  | 	 * @param string $data | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_data($data) { | 	public function set_data($data) { | ||||||
| 		$this->data = $data; | 		$this->data = $data; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the recommended download filename | 	 * Set the recommended download filename. | ||||||
|  | 	 * @param string $filename | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_filename($filename) { | 	public function set_filename($filename) { | ||||||
| 		$this->filename = $filename; | 		$this->filename = $filename; | ||||||
| @ -86,12 +93,13 @@ class Page { | |||||||
| 	/** @name "redirect" mode */ | 	/** @name "redirect" mode */ | ||||||
| 	//@{
 | 	//@{
 | ||||||
| 
 | 
 | ||||||
| 	/** @private */ | 	/** @var string */ | ||||||
| 	var $redirect = ""; | 	private $redirect = ""; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the URL to redirect to (remember to use make_link() if linking | 	 * Set the URL to redirect to (remember to use make_link() if linking | ||||||
| 	 * to a page in the same site) | 	 * to a page in the same site). | ||||||
|  | 	 * @param string $redirect | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_redirect($redirect) { | 	public function set_redirect($redirect) { | ||||||
| 		$this->redirect = $redirect; | 		$this->redirect = $redirect; | ||||||
| @ -103,39 +111,56 @@ class Page { | |||||||
| 	/** @name "page" mode */ | 	/** @name "page" mode */ | ||||||
| 	//@{
 | 	//@{
 | ||||||
| 
 | 
 | ||||||
| 	/** @privatesection */ | 	/** @var string */ | ||||||
| 	var $title = ""; | 	public $title = ""; | ||||||
| 	var $heading = ""; | 
 | ||||||
| 	var $subheading = ""; | 	/** @var string */ | ||||||
| 	var $quicknav = ""; | 	public $heading = ""; | ||||||
| 	var $html_headers = array(); | 
 | ||||||
| 	var $http_headers = array(); | 	/** @var string */ | ||||||
| 	var $blocks = array(); | 	public $subheading = ""; | ||||||
| 	/** @publicsection */ | 
 | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $quicknav = ""; | ||||||
|  | 
 | ||||||
|  | 	/** @var string[] */ | ||||||
|  | 	public $html_headers = array(); | ||||||
|  | 
 | ||||||
|  | 	/** @var string[] */ | ||||||
|  | 	public $http_headers = array(); | ||||||
|  | 
 | ||||||
|  | 	/** @var Block[] */ | ||||||
|  | 	public $blocks = array(); | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the window title | 	 * Set the window title. | ||||||
|  | 	 * @param string $title | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_title($title) { | 	public function set_title($title) { | ||||||
| 		$this->title = $title; | 		$this->title = $title; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the main heading | 	 * Set the main heading. | ||||||
|  | 	 * @param string $heading | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_heading($heading) { | 	public function set_heading($heading) { | ||||||
| 		$this->heading = $heading; | 		$this->heading = $heading; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Set the sub heading | 	 * Set the sub heading. | ||||||
|  | 	 * @param string $subheading | ||||||
| 	 */ | 	 */ | ||||||
| 	public function set_subheading($subheading) { | 	public function set_subheading($subheading) { | ||||||
| 		$this->subheading = $subheading; | 		$this->subheading = $subheading; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Add a line to the HTML head section | 	 * Add a line to the HTML head section. | ||||||
|  | 	 * @param string $line | ||||||
|  | 	 * @param int $position | ||||||
| 	 */ | 	 */ | ||||||
| 	public function add_html_header($line, $position=50) { | 	public function add_html_header($line, $position=50) { | ||||||
| 		while(isset($this->html_headers[$position])) $position++; | 		while(isset($this->html_headers[$position])) $position++; | ||||||
| @ -144,6 +169,8 @@ class Page { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Add a http header to be sent to the client. | 	 * Add a http header to be sent to the client. | ||||||
|  | 	 * @param string $line | ||||||
|  | 	 * @param int $position | ||||||
| 	 */ | 	 */ | ||||||
| 	public function add_http_header($line, $position=50) { | 	public function add_http_header($line, $position=50) { | ||||||
| 		while(isset($this->http_headers[$position])) $position++; | 		while(isset($this->http_headers[$position])) $position++; | ||||||
| @ -152,6 +179,7 @@ class Page { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get all the HTML headers that are currently set and return as a string. | 	 * Get all the HTML headers that are currently set and return as a string. | ||||||
|  | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_all_html_headers() { | 	public function get_all_html_headers() { | ||||||
| 		$data = ''; | 		$data = ''; | ||||||
| @ -162,14 +190,15 @@ class Page { | |||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	/** | 	/** | ||||||
| 	 * Removes all currently set HTML headers. (Be careful..) | 	 * Removes all currently set HTML headers (Be careful..). | ||||||
| 	 */ | 	 */ | ||||||
| 	public function delete_all_html_headers() { | 	public function delete_all_html_headers() { | ||||||
| 		$this->html_headers = array(); | 		$this->html_headers = array(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Add a Block of data | 	 * Add a Block of data to the page. | ||||||
|  | 	 * @param Block $block | ||||||
| 	 */ | 	 */ | ||||||
| 	public function add_block(Block $block) { | 	public function add_block(Block $block) { | ||||||
| 		$this->blocks[] = $block; | 		$this->blocks[] = $block; | ||||||
| @ -180,7 +209,7 @@ class Page { | |||||||
| 	// ==============================================
 | 	// ==============================================
 | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Display the page according to the mode and data given | 	 * Display the page according to the mode and data given. | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display() { | 	public function display() { | ||||||
| 		global $page, $user; | 		global $page, $user; | ||||||
| @ -263,7 +292,7 @@ class Page { | |||||||
| 			$css_files[] = $css; | 			$css_files[] = $css; | ||||||
| 			$css_latest = max($css_latest, filemtime($css)); | 			$css_latest = max($css_latest, filemtime($css)); | ||||||
| 		} | 		} | ||||||
| 		$css_cache_file = data_path("cache/style.$css_latest.css"); | 		$css_cache_file = data_path("cache/style.$theme_name.$css_latest.css"); | ||||||
| 		if(!file_exists($css_cache_file)) { | 		if(!file_exists($css_cache_file)) { | ||||||
| 			$css_data = ""; | 			$css_data = ""; | ||||||
| 			foreach($css_files as $file) { | 			foreach($css_files as $file) { | ||||||
| @ -283,7 +312,7 @@ class Page { | |||||||
| 			$js_files[] = $js; | 			$js_files[] = $js; | ||||||
| 			$js_latest = max($js_latest, filemtime($js)); | 			$js_latest = max($js_latest, filemtime($js)); | ||||||
| 		} | 		} | ||||||
| 		$js_cache_file = data_path("cache/script.$js_latest.js"); | 		$js_cache_file = data_path("cache/script.$theme_name.$js_latest.js"); | ||||||
| 		if(!file_exists($js_cache_file)) { | 		if(!file_exists($js_cache_file)) { | ||||||
| 			$js_data = ""; | 			$js_data = ""; | ||||||
| 			foreach($js_files as $file) { | 			foreach($js_files as $file) { | ||||||
|  | |||||||
| @ -1,4 +1,6 @@ | |||||||
| <?php | <?php | ||||||
|  | require_once "lib/password.php"; | ||||||
|  | 
 | ||||||
| /** @private */ | /** @private */ | ||||||
| function _new_user($row) { | function _new_user($row) { | ||||||
| 	return new User($row); | 	return new User($row); | ||||||
| @ -6,9 +8,11 @@ function _new_user($row) { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  |  * Class User | ||||||
|  |  * | ||||||
|  * An object representing a row in the "users" table. |  * An object representing a row in the "users" table. | ||||||
|  * |  * | ||||||
|  * The currently logged in user will always be accessible via the global variable $user |  * The currently logged in user will always be accessible via the global variable $user. | ||||||
|  */ |  */ | ||||||
| class User { | class User { | ||||||
| 	/** @var int */ | 	/** @var int */ | ||||||
| @ -22,10 +26,11 @@ class User { | |||||||
| 
 | 
 | ||||||
| 	public $join_date; | 	public $join_date; | ||||||
| 
 | 
 | ||||||
|  | 	/** @var string */ | ||||||
| 	public $passhash; | 	public $passhash; | ||||||
| 
 | 
 | ||||||
| 	/** @var UserClass */ | 	/** @var UserClass */ | ||||||
| 	var $class; | 	public $class; | ||||||
| 
 | 
 | ||||||
| 	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||||||
| 	* Initialisation                                               * | 	* Initialisation                                               * | ||||||
| @ -38,7 +43,9 @@ class User { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * One will very rarely construct a user directly, more common | 	 * One will very rarely construct a user directly, more common | ||||||
| 	 * would be to use User::by_id, User::by_session, etc | 	 * would be to use User::by_id, User::by_session, etc. | ||||||
|  | 	 * | ||||||
|  | 	 * @param mixed $row | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct($row) { | 	public function __construct($row) { | ||||||
| 		global $_user_classes; | 		global $_user_classes; | ||||||
| @ -60,7 +67,7 @@ class User { | |||||||
| 	 */ | 	 */ | ||||||
| 	public static function by_session(/*string*/ $name, /*string*/ $session) { | 	public static function by_session(/*string*/ $name, /*string*/ $session) { | ||||||
| 		global $config, $database; | 		global $config, $database; | ||||||
| 		$row = $database->cache->get("user-session-$name-$session"); | 		$row = $database->cache->get("user-session:$name-$session"); | ||||||
| 		if(!$row) { | 		if(!$row) { | ||||||
| 			if($database->get_driver_name() === "mysql") { | 			if($database->get_driver_name() === "mysql") { | ||||||
| 				$query = "SELECT * FROM users WHERE name = :name AND md5(concat(pass, :ip)) = :sess"; | 				$query = "SELECT * FROM users WHERE name = :name AND md5(concat(pass, :ip)) = :sess"; | ||||||
| @ -69,7 +76,7 @@ class User { | |||||||
| 				$query = "SELECT * FROM users WHERE name = :name AND md5(pass || :ip) = :sess"; | 				$query = "SELECT * FROM users WHERE name = :name AND md5(pass || :ip) = :sess"; | ||||||
| 			} | 			} | ||||||
| 			$row = $database->get_row($query, array("name"=>$name, "ip"=>get_session_ip($config), "sess"=>$session)); | 			$row = $database->get_row($query, array("name"=>$name, "ip"=>get_session_ip($config), "sess"=>$session)); | ||||||
| 			$database->cache->set("user-session-$name-$session", $row, 600); | 			$database->cache->set("user-session:$name-$session", $row, 600); | ||||||
| 		} | 		} | ||||||
| 		return is_null($row) ? null : new User($row); | 		return is_null($row) ? null : new User($row); | ||||||
| 	} | 	} | ||||||
| @ -104,18 +111,23 @@ class User { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Construct a User by name and hash. | 	 * Construct a User by name and password. | ||||||
| 	 * @param string $name | 	 * @param string $name | ||||||
| 	 * @param string $hash | 	 * @param string $pass | ||||||
| 	 * @return null|User | 	 * @return null|User | ||||||
| 	 */ | 	 */ | ||||||
| 	public static function by_name_and_hash(/*string*/ $name, /*string*/ $hash) { | 	public static function by_name_and_pass(/*string*/ $name, /*string*/ $pass) { | ||||||
| 		assert(is_string($name)); | 		assert(is_string($name)); | ||||||
| 		assert(is_string($hash)); | 		assert(is_string($pass)); | ||||||
| 		assert(strlen($hash) == 32); | 		$user = User::by_name($name); | ||||||
| 		global $database; | 		if($user) { | ||||||
| 		$row = $database->get_row($database->scoreql_to_sql("SELECT * FROM users WHERE SCORE_STRNORM(name) = SCORE_STRNORM(:name) AND pass = :hash"), array("name"=>$name, "hash"=>$hash)); | 			if($user->passhash == md5(strtolower($name) . $pass)) { | ||||||
| 		return is_null($row) ? null : new User($row); | 				$user->set_password($pass); | ||||||
|  | 			} | ||||||
|  | 			if(password_verify($pass, $user->passhash)) { | ||||||
|  | 				return $user; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -145,7 +157,7 @@ class User { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Test if this user is anonymous (not logged in) | 	 * Test if this user is anonymous (not logged in). | ||||||
| 	 * | 	 * | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| @ -155,7 +167,7 @@ class User { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Test if this user is logged in | 	 * Test if this user is logged in. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| @ -165,7 +177,7 @@ class User { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Test if this user is an administrator | 	 * Test if this user is an administrator. | ||||||
| 	 * | 	 * | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| @ -188,11 +200,14 @@ class User { | |||||||
| 	 */ | 	 */ | ||||||
| 	public function set_password(/*string*/ $password) { | 	public function set_password(/*string*/ $password) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$hash = md5(strtolower($this->name) . $password); | 		$this->passhash = password_hash($password, PASSWORD_BCRYPT); | ||||||
| 		$database->Execute("UPDATE users SET pass=:hash WHERE id=:id", array("hash"=>$hash, "id"=>$this->id)); | 		$database->Execute("UPDATE users SET pass=:hash WHERE id=:id", array("hash"=>$this->passhash, "id"=>$this->id)); | ||||||
| 		log_info("core-user", 'Set password for '.$this->name); | 		log_info("core-user", 'Set password for '.$this->name); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $address | ||||||
|  | 	 */ | ||||||
| 	public function set_email(/*string*/ $address) { | 	public function set_email(/*string*/ $address) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$database->Execute("UPDATE users SET email=:email WHERE id=:id", array("email"=>$address, "id"=>$this->id)); | 		$database->Execute("UPDATE users SET email=:email WHERE id=:id", array("email"=>$address, "id"=>$this->id)); | ||||||
| @ -201,7 +216,8 @@ class User { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get a snippet of HTML which will render the user's avatar, be that | 	 * Get a snippet of HTML which will render the user's avatar, be that | ||||||
| 	 * a local file, a remote file, a gravatar, a something else, etc | 	 * a local file, a remote file, a gravatar, a something else, etc. | ||||||
|  | 	 * | ||||||
| 	 * @return String of HTML | 	 * @return String of HTML | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_avatar_html() { | 	public function get_avatar_html() { | ||||||
| @ -224,14 +240,14 @@ class User { | |||||||
| 	 * Get an auth token to be used in POST forms | 	 * Get an auth token to be used in POST forms | ||||||
| 	 * | 	 * | ||||||
| 	 * password = secret, avoid storing directly | 	 * password = secret, avoid storing directly | ||||||
| 	 * passhash = md5(password), so someone who gets to the database can't get passwords | 	 * passhash = bcrypt(password), so someone who gets to the database can't get passwords | ||||||
| 	 * sesskey  = md5(passhash . IP), so if it gets sniffed it can't be used from another IP, | 	 * sesskey  = md5(passhash . IP), so if it gets sniffed it can't be used from another IP, | ||||||
| 	 *            and it can't be used to get the passhash to generate new sesskeys | 	 *            and it can't be used to get the passhash to generate new sesskeys | ||||||
| 	 * authtok  = md5(sesskey, salt), presented to the user in web forms, to make sure that | 	 * authtok  = md5(sesskey, salt), presented to the user in web forms, to make sure that | ||||||
| 	 *            the form was generated within the session. Salted and re-hashed so that | 	 *            the form was generated within the session. Salted and re-hashed so that | ||||||
| 	 *            reading a web page from the user's cache doesn't give access to the session key | 	 *            reading a web page from the user's cache doesn't give access to the session key | ||||||
| 	 * | 	 * | ||||||
| 	 * @return String containing auth token (MD5sum) | 	 * @return string A string containing auth token (MD5sum) | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_auth_token() { | 	public function get_auth_token() { | ||||||
| 		global $config; | 		global $config; | ||||||
|  | |||||||
| @ -1,11 +1,34 @@ | |||||||
| <?php | <?php | ||||||
|  | /** | ||||||
|  |  * @global UserClass[] $_user_classes | ||||||
|  |  */ | ||||||
| $_user_classes = array(); | $_user_classes = array(); | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Class UserClass | ||||||
|  |  */ | ||||||
| class UserClass { | class UserClass { | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @var null|string | ||||||
|  | 	 */ | ||||||
| 	public $name = null; | 	public $name = null; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @var \UserClass|null | ||||||
|  | 	 */ | ||||||
| 	public $parent = null; | 	public $parent = null; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @var array | ||||||
|  | 	 */ | ||||||
| 	public $abilities = array(); | 	public $abilities = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $parent | ||||||
|  | 	 * @param array $abilities | ||||||
|  | 	 */ | ||||||
| 	public function __construct($name, $parent=null, $abilities=array()) { | 	public function __construct($name, $parent=null, $abilities=array()) { | ||||||
| 		global $_user_classes; | 		global $_user_classes; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -124,6 +124,12 @@ function no_escape($input) { | |||||||
| 	return $input; | 	return $input; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param string $name | ||||||
|  |  * @param array $attrs | ||||||
|  |  * @param array $children | ||||||
|  |  * @return string | ||||||
|  |  */ | ||||||
| function xml_tag($name, $attrs=array(), $children=array()) { | function xml_tag($name, $attrs=array(), $children=array()) { | ||||||
| 	$xml = "<$name "; | 	$xml = "<$name "; | ||||||
| 	foreach($attrs as $k => $v) { | 	foreach($attrs as $k => $v) { | ||||||
| @ -427,6 +433,10 @@ function make_form($target, $method="POST", $multipart=False, $form_id="", $onsu | |||||||
| 	return '<form action="'.$target.'" method="'.$method.'" '.$extra.'>'.$auth; | 	return '<form action="'.$target.'" method="'.$method.'" '.$extra.'>'.$auth; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param string $file The filename | ||||||
|  |  * @return string | ||||||
|  |  */ | ||||||
| function mtimefile($file) { | function mtimefile($file) { | ||||||
| 	$data_href = get_base_href(); | 	$data_href = get_base_href(); | ||||||
| 	$mtime = filemtime($file); | 	$mtime = filemtime($file); | ||||||
| @ -445,8 +455,11 @@ function get_theme() { | |||||||
| 	return $theme; | 	return $theme; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* | /** | ||||||
|  * like glob, with support for matching very long patterns with braces |  * Like glob, with support for matching very long patterns with braces. | ||||||
|  |  * | ||||||
|  |  * @param string $pattern | ||||||
|  |  * @return array | ||||||
|  */ |  */ | ||||||
| function zglob($pattern) { | function zglob($pattern) { | ||||||
| 	$results = array(); | 	$results = array(); | ||||||
| @ -470,6 +483,9 @@ function zglob($pattern) { | |||||||
| * CAPTCHA abstraction                                                       * | * CAPTCHA abstraction                                                       * | ||||||
| \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @return string | ||||||
|  |  */ | ||||||
| function captcha_get_html() { | function captcha_get_html() { | ||||||
| 	global $config, $user; | 	global $config, $user; | ||||||
| 
 | 
 | ||||||
| @ -492,6 +508,9 @@ function captcha_get_html() { | |||||||
| 	return $captcha; | 	return $captcha; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @return bool | ||||||
|  |  */ | ||||||
| function captcha_check() { | function captcha_check() { | ||||||
| 	global $config, $user; | 	global $config, $user; | ||||||
| 
 | 
 | ||||||
| @ -593,7 +612,10 @@ function getMimeType($file, $ext="", $list=false) { | |||||||
| 	return 'application/octet-stream'; | 	return 'application/octet-stream'; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | /** | ||||||
|  |  * @param string $mime_type | ||||||
|  |  * @return bool|string | ||||||
|  |  */ | ||||||
| function getExtension ($mime_type){ | function getExtension ($mime_type){ | ||||||
| 	if(empty($mime_type)){ | 	if(empty($mime_type)){ | ||||||
| 		return false; | 		return false; | ||||||
| @ -608,7 +630,7 @@ function getExtension ($mime_type){ | |||||||
|  * @private |  * @private | ||||||
|  */ |  */ | ||||||
| function _version_check() { | function _version_check() { | ||||||
| 	$min_version = "5.3.0"; | 	$min_version = "5.3.7"; | ||||||
| 	if(version_compare(PHP_VERSION, $min_version) == -1) { | 	if(version_compare(PHP_VERSION, $min_version) == -1) { | ||||||
| 		print " | 		print " | ||||||
| Currently SCore Engine doesn't support versions of PHP lower than $min_version -- | Currently SCore Engine doesn't support versions of PHP lower than $min_version -- | ||||||
| @ -762,6 +784,11 @@ function get_prefixed_cookie(/*string*/ $name) { | |||||||
|  * The counterpart for get_prefixed_cookie, this works like php's |  * The counterpart for get_prefixed_cookie, this works like php's | ||||||
|  * setcookie method, but prepends the site-wide cookie prefix to |  * setcookie method, but prepends the site-wide cookie prefix to | ||||||
|  * the $name argument before doing anything. |  * the $name argument before doing anything. | ||||||
|  |  * | ||||||
|  |  * @param string $name | ||||||
|  |  * @param string $value | ||||||
|  |  * @param int $time | ||||||
|  |  * @param string $path | ||||||
|  */ |  */ | ||||||
| function set_prefixed_cookie($name, $value, $time, $path) { | function set_prefixed_cookie($name, $value, $time, $path) { | ||||||
| 	global $config; | 	global $config; | ||||||
| @ -770,13 +797,16 @@ function set_prefixed_cookie($name, $value, $time, $path) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Set (or extend) a flash-message cookie |  * Set (or extend) a flash-message cookie. | ||||||
|  * |  * | ||||||
|  * This can optionally be done at the same time as saving a log message with log_*() |  * This can optionally be done at the same time as saving a log message with log_*() | ||||||
|  * |  * | ||||||
|  * Generally one should flash a message in onPageRequest and log a message wherever |  * Generally one should flash a message in onPageRequest and log a message wherever | ||||||
|  * the action actually takes place (eg onWhateverElse) - but much of the time, actions |  * the action actually takes place (eg onWhateverElse) - but much of the time, actions | ||||||
|  * are taken from within onPageRequest... |  * are taken from within onPageRequest... | ||||||
|  |  * | ||||||
|  |  * @param string $text | ||||||
|  |  * @param string $type | ||||||
|  */ |  */ | ||||||
| function flash_message(/*string*/ $text, /*string*/ $type="info") { | function flash_message(/*string*/ $text, /*string*/ $type="info") { | ||||||
| 	$current = get_prefixed_cookie("flash_message"); | 	$current = get_prefixed_cookie("flash_message"); | ||||||
| @ -816,10 +846,9 @@ function get_base_href() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A shorthand way to send a TextFormattingEvent and get the |  * A shorthand way to send a TextFormattingEvent and get the results. | ||||||
|  * results |  | ||||||
|  * |  * | ||||||
|  * @param $string |  * @param string $string | ||||||
|  * @return string |  * @return string | ||||||
|  */ |  */ | ||||||
| function format_text(/*string*/ $string) { | function format_text(/*string*/ $string) { | ||||||
| @ -828,6 +857,12 @@ function format_text(/*string*/ $string) { | |||||||
| 	return $tfe->formatted; | 	return $tfe->formatted; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param string $base | ||||||
|  |  * @param string $hash | ||||||
|  |  * @param bool $create | ||||||
|  |  * @return string | ||||||
|  |  */ | ||||||
| function warehouse_path(/*string*/ $base, /*string*/ $hash, /*bool*/ $create=true) { | function warehouse_path(/*string*/ $base, /*string*/ $hash, /*bool*/ $create=true) { | ||||||
| 	$ab = substr($hash, 0, 2); | 	$ab = substr($hash, 0, 2); | ||||||
| 	$cd = substr($hash, 2, 2); | 	$cd = substr($hash, 2, 2); | ||||||
| @ -841,12 +876,21 @@ function warehouse_path(/*string*/ $base, /*string*/ $hash, /*bool*/ $create=tru | |||||||
| 	return $pa; | 	return $pa; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param string $filename | ||||||
|  |  * @return string | ||||||
|  |  */ | ||||||
| function data_path($filename) { | function data_path($filename) { | ||||||
| 	$filename = "data/" . $filename; | 	$filename = "data/" . $filename; | ||||||
| 	if(!file_exists(dirname($filename))) mkdir(dirname($filename), 0755, true); | 	if(!file_exists(dirname($filename))) mkdir(dirname($filename), 0755, true); | ||||||
| 	return $filename; | 	return $filename; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param string $url | ||||||
|  |  * @param string $mfile | ||||||
|  |  * @return array|bool | ||||||
|  |  */ | ||||||
| function transload($url, $mfile) { | function transload($url, $mfile) { | ||||||
| 	global $config; | 	global $config; | ||||||
| 
 | 
 | ||||||
| @ -935,15 +979,37 @@ if (!function_exists('http_parse_headers')) { #http://www.php.net/manual/en/func | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function findHeader ($headers, $name){ | ||||||
|  | 	//HTTP Headers can sometimes be lowercase which will cause issues.
 | ||||||
|  | 	//In cases like these, we need to make sure to check for them if the camelcase version does not exist.
 | ||||||
|  | 	$header = FALSE; | ||||||
|  | 
 | ||||||
|  | 	if(array_key_exists($name, $headers)){ | ||||||
|  | 		$header = $headers[$name]; | ||||||
|  | 	}else{ | ||||||
|  | 		$headers = array_change_key_case($headers); | ||||||
|  | 		if(array_key_exists(strtolower($name), $headers)){ | ||||||
|  | 			$header = $headers[strtolower($name)]; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return $header; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| $_included = array(); | $_included = array(); | ||||||
| /** | /** | ||||||
|  * Get the active contents of a .php file |  * Get the active contents of a .php file | ||||||
|  |  * | ||||||
|  |  * @param string $fname | ||||||
|  |  * @return string|null | ||||||
|  */ |  */ | ||||||
| function manual_include($fname) { | function manual_include($fname) { | ||||||
| 	if(!file_exists($fname)) return; |  | ||||||
| 
 |  | ||||||
| 	global $_included; | 	global $_included; | ||||||
| 	if(in_array($fname, $_included)) return; | 
 | ||||||
|  | 	if(!file_exists($fname)) return null; | ||||||
|  | 
 | ||||||
|  | 	if(in_array($fname, $_included)) return null; | ||||||
|  | 
 | ||||||
| 	$_included[] = $fname; | 	$_included[] = $fname; | ||||||
| 
 | 
 | ||||||
| 	print "$fname\n"; | 	print "$fname\n"; | ||||||
| @ -990,6 +1056,12 @@ define("SCORE_LOG_NOTSET", 0); | |||||||
|  * $flash = null (default) - log to server only, no flash message |  * $flash = null (default) - log to server only, no flash message | ||||||
|  * $flash = true           - show the message to the user as well |  * $flash = true           - show the message to the user as well | ||||||
|  * $flash = "some string"  - log the message, flash the string |  * $flash = "some string"  - log the message, flash the string | ||||||
|  |  * | ||||||
|  |  * @param string $section | ||||||
|  |  * @param int $priority | ||||||
|  |  * @param string $message | ||||||
|  |  * @param null|bool|string $flash | ||||||
|  |  * @param array $args | ||||||
|  */ |  */ | ||||||
| function log_msg(/*string*/ $section, /*int*/ $priority, /*string*/ $message, $flash=null, $args=array()) { | function log_msg(/*string*/ $section, /*int*/ $priority, /*string*/ $message, $flash=null, $args=array()) { | ||||||
| 	send_event(new LogEvent($section, $priority, $message, $args)); | 	send_event(new LogEvent($section, $priority, $message, $args)); | ||||||
| @ -1012,10 +1084,13 @@ function log_warning( /*string*/ $section, /*string*/ $message, $flash=null, $ar | |||||||
| function log_error(   /*string*/ $section, /*string*/ $message, $flash=null, $args=array()) {log_msg($section, SCORE_LOG_ERROR, $message, $flash, $args);} | function log_error(   /*string*/ $section, /*string*/ $message, $flash=null, $args=array()) {log_msg($section, SCORE_LOG_ERROR, $message, $flash, $args);} | ||||||
| function log_critical(/*string*/ $section, /*string*/ $message, $flash=null, $args=array()) {log_msg($section, SCORE_LOG_CRITICAL, $message, $flash, $args);} | function log_critical(/*string*/ $section, /*string*/ $message, $flash=null, $args=array()) {log_msg($section, SCORE_LOG_CRITICAL, $message, $flash, $args);} | ||||||
| 
 | 
 | ||||||
| /** | 
 | ||||||
|  * Get a unique ID for this request, useful for grouping log messages |  | ||||||
|  */ |  | ||||||
| $_request_id = null; | $_request_id = null; | ||||||
|  | /** | ||||||
|  |  * Get a unique ID for this request, useful for grouping log messages. | ||||||
|  |  * | ||||||
|  |  * @return null|string | ||||||
|  |  */ | ||||||
| function get_request_id() { | function get_request_id() { | ||||||
| 	global $_request_id; | 	global $_request_id; | ||||||
| 	if(!$_request_id) { | 	if(!$_request_id) { | ||||||
| @ -1197,7 +1272,11 @@ function full_copy($source, $target) { | |||||||
| $_event_listeners = array(); | $_event_listeners = array(); | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Register an Extension |  * Register an Extension. | ||||||
|  |  * | ||||||
|  |  * @param Extension $extension | ||||||
|  |  * @param int $pos | ||||||
|  |  * @param array $events | ||||||
|  */ |  */ | ||||||
| function add_event_listener(Extension $extension, $pos=50, $events=array()) { | function add_event_listener(Extension $extension, $pos=50, $events=array()) { | ||||||
| 	global $_event_listeners; | 	global $_event_listeners; | ||||||
| @ -1214,7 +1293,9 @@ function add_event_listener(Extension $extension, $pos=50, $events=array()) { | |||||||
| $_event_count = 0; | $_event_count = 0; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Send an event to all registered Extensions |  * Send an event to all registered Extensions. | ||||||
|  |  * | ||||||
|  |  * @param Event $event | ||||||
|  */ |  */ | ||||||
| function send_event(Event $event) { | function send_event(Event $event) { | ||||||
| 	global $_event_listeners, $_event_count; | 	global $_event_listeners, $_event_count; | ||||||
| @ -1227,7 +1308,9 @@ function send_event(Event $event) { | |||||||
| 	ksort($my_event_listeners); | 	ksort($my_event_listeners); | ||||||
| 	foreach($my_event_listeners as $listener) { | 	foreach($my_event_listeners as $listener) { | ||||||
| 		ctx_log_start(get_class($listener)); | 		ctx_log_start(get_class($listener)); | ||||||
|  | 		if(method_exists($listener, $method_name)) { | ||||||
| 			$listener->$method_name($event); | 			$listener->$method_name($event); | ||||||
|  | 		} | ||||||
| 		ctx_log_endok(); | 		ctx_log_endok(); | ||||||
| 	} | 	} | ||||||
| 	$_event_count++; | 	$_event_count++; | ||||||
| @ -1248,7 +1331,7 @@ $_load_start = microtime(true); | |||||||
|  * Collects some debug information (execution time, memory usage, queries, etc) |  * Collects some debug information (execution time, memory usage, queries, etc) | ||||||
|  * and formats it to stick in the footer of the page. |  * and formats it to stick in the footer of the page. | ||||||
|  * |  * | ||||||
|  * @return String of debug info to add to the page. |  * @return string debug info to add to the page. | ||||||
|  */ |  */ | ||||||
| function get_debug_info() { | function get_debug_info() { | ||||||
| 	global $config, $_event_count, $database, $_execs, $_load_start; | 	global $config, $_event_count, $database, $_execs, $_load_start; | ||||||
| @ -1261,12 +1344,13 @@ function get_debug_info() { | |||||||
| 	else { | 	else { | ||||||
| 		$commit = " (".$config->get_string("commit_hash").")"; | 		$commit = " (".$config->get_string("commit_hash").")"; | ||||||
| 	} | 	} | ||||||
| 	$time = sprintf("%5.2f", microtime(true) - $_load_start); | 	$time = sprintf("%.2f", microtime(true) - $_load_start); | ||||||
|  | 	$dbtime = sprintf("%.2f", $database->dbtime); | ||||||
| 	$i_files = count(get_included_files()); | 	$i_files = count(get_included_files()); | ||||||
| 	$hits = $database->cache->get_hits(); | 	$hits = $database->cache->get_hits(); | ||||||
| 	$miss = $database->cache->get_misses(); | 	$miss = $database->cache->get_misses(); | ||||||
| 
 | 
 | ||||||
| 	$debug = "<br>Took $time seconds and {$i_mem}MB of RAM"; | 	$debug = "<br>Took $time seconds (db:$dbtime) and {$i_mem}MB of RAM"; | ||||||
| 	$debug .= "; Used $i_files files and $_execs queries"; | 	$debug .= "; Used $i_files files and $_execs queries"; | ||||||
| 	$debug .= "; Sent $_event_count events"; | 	$debug .= "; Sent $_event_count events"; | ||||||
| 	$debug .= "; $hits cache hits and $miss misses"; | 	$debug .= "; $hits cache hits and $miss misses"; | ||||||
| @ -1282,6 +1366,10 @@ function get_debug_info() { | |||||||
| 
 | 
 | ||||||
| /** @privatesection */ | /** @privatesection */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param array|string $arr | ||||||
|  |  * @return array|string | ||||||
|  |  */ | ||||||
| function _stripslashes_r($arr) { | function _stripslashes_r($arr) { | ||||||
| 	return is_array($arr) ? array_map('_stripslashes_r', $arr) : stripslashes($arr); | 	return is_array($arr) ? array_map('_stripslashes_r', $arr) : stripslashes($arr); | ||||||
| } | } | ||||||
| @ -1325,6 +1413,10 @@ function _sanitise_environment() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param string $_theme | ||||||
|  |  * @return array | ||||||
|  |  */ | ||||||
| function _get_themelet_files($_theme) { | function _get_themelet_files($_theme) { | ||||||
| 	$base_themelets = array(); | 	$base_themelets = array(); | ||||||
| 	if(file_exists('themes/'.$_theme.'/custompage.class.php')) $base_themelets[] = 'themes/'.$_theme.'/custompage.class.php'; | 	if(file_exists('themes/'.$_theme.'/custompage.class.php')) $base_themelets[] = 'themes/'.$_theme.'/custompage.class.php'; | ||||||
| @ -1407,6 +1499,7 @@ function _load_extensions() { | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Used to display fatal errors to the web user. |  * Used to display fatal errors to the web user. | ||||||
|  |  * @param Exception $e | ||||||
|  */ |  */ | ||||||
| function _fatal_error(Exception $e) { | function _fatal_error(Exception $e) { | ||||||
| 	$version = VERSION; | 	$version = VERSION; | ||||||
| @ -1438,6 +1531,9 @@ function _fatal_error(Exception $e) { | |||||||
|  * |  * | ||||||
|  * Necessary because various servers and various clients |  * Necessary because various servers and various clients | ||||||
|  * think that / is special... |  * think that / is special... | ||||||
|  |  * | ||||||
|  |  * @param string $str | ||||||
|  |  * @return string | ||||||
|  */ |  */ | ||||||
| function _decaret($str) { | function _decaret($str) { | ||||||
| 	$out = ""; | 	$out = ""; | ||||||
| @ -1456,6 +1552,9 @@ function _decaret($str) { | |||||||
| 	return $out; | 	return $out; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @return User | ||||||
|  |  */ | ||||||
| function _get_user() { | function _get_user() { | ||||||
| 	global $config; | 	global $config; | ||||||
| 	$user = null; | 	$user = null; | ||||||
|  | |||||||
| @ -17,22 +17,33 @@ | |||||||
|  *  <br>Download the contents of the database in plain text format, useful |  *  <br>Download the contents of the database in plain text format, useful | ||||||
|  *  for backups. |  *  for backups. | ||||||
|  *  <p>Image dump: |  *  <p>Image dump: | ||||||
|  *  <br>Download all the images as a .zip file |  *  <br>Download all the images as a .zip file (Requires ZipArchive) | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Sent when the admin page is ready to be added to |  * Sent when the admin page is ready to be added to | ||||||
|  */ |  */ | ||||||
| class AdminBuildingEvent extends Event { | class AdminBuildingEvent extends Event { | ||||||
| 	var $page; | 	/** @var \Page */ | ||||||
|  | 	public $page; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Page $page) { | 	public function __construct(Page $page) { | ||||||
| 		$this->page = $page; | 		$this->page = $page; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class AdminActionEvent extends Event { | class AdminActionEvent extends Event { | ||||||
| 	var $action; | 	/** @var string */ | ||||||
| 	var $redirect = true; | 	public $action; | ||||||
|  | 	/** @var bool */ | ||||||
|  | 	public $redirect = true; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $action | ||||||
|  | 	 */ | ||||||
| 	public function __construct(/*string*/ $action) { | 	public function __construct(/*string*/ $action) { | ||||||
| 		$this->action = $action; | 		$this->action = $action; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -12,6 +12,12 @@ class AdminPageTheme extends Themelet { | |||||||
| 		$page->add_block(new NavBlock()); | 		$page->add_block(new NavBlock()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $action | ||||||
|  | 	 * @param bool $protected | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function button(/*string*/ $name, /*string*/ $action, /*boolean*/ $protected=false) { | 	protected function button(/*string*/ $name, /*string*/ $action, /*boolean*/ $protected=false) { | ||||||
| 		$c_protected = $protected ? " protected" : ""; | 		$c_protected = $protected ? " protected" : ""; | ||||||
| 		$html = make_form(make_link("admin/$action"), "POST", false, null, null, "admin$c_protected"); | 		$html = make_form(make_link("admin/$action"), "POST", false, null, null, "admin$c_protected"); | ||||||
| @ -39,6 +45,7 @@ class AdminPageTheme extends Themelet { | |||||||
| 		$html = ""; | 		$html = ""; | ||||||
| 		$html .= $this->button("All tags to lowercase", "lowercase_all_tags", true); | 		$html .= $this->button("All tags to lowercase", "lowercase_all_tags", true); | ||||||
| 		$html .= $this->button("Recount tag use", "recount_tag_use", false); | 		$html .= $this->button("Recount tag use", "recount_tag_use", false); | ||||||
|  | 		if(class_exists('ZipArchive')) | ||||||
| 			$html .= $this->button("Download all images", "download_all_images", false); | 			$html .= $this->button("Download all images", "download_all_images", false); | ||||||
|         $html .= $this->button("Download database contents", "database_dump", false); |         $html .= $this->button("Download database contents", "database_dump", false); | ||||||
| 		if($database->get_driver_name() == "mysql") | 		if($database->get_driver_name() == "mysql") | ||||||
|  | |||||||
| @ -11,9 +11,15 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class AddAliasEvent extends Event { | class AddAliasEvent extends Event { | ||||||
| 	var $oldtag; | 	/** @var string  */ | ||||||
| 	var $newtag; | 	public $oldtag; | ||||||
|  | 	/** @var string  */ | ||||||
|  | 	public $newtag; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $oldtag | ||||||
|  | 	 * @param string $newtag | ||||||
|  | 	 */ | ||||||
| 	public function __construct($oldtag, $newtag) { | 	public function __construct($oldtag, $newtag) { | ||||||
| 		$this->oldtag = trim($oldtag); | 		$this->oldtag = trim($oldtag); | ||||||
| 		$this->newtag = trim($newtag); | 		$this->newtag = trim($newtag); | ||||||
| @ -124,6 +130,10 @@ class AliasEditor extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Database $database | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function get_alias_csv(Database $database) { | 	private function get_alias_csv(Database $database) { | ||||||
| 		$csv = ""; | 		$csv = ""; | ||||||
| 		$aliases = $database->get_pairs("SELECT oldtag, newtag FROM aliases ORDER BY newtag"); | 		$aliases = $database->get_pairs("SELECT oldtag, newtag FROM aliases ORDER BY newtag"); | ||||||
| @ -133,6 +143,10 @@ class AliasEditor extends Extension { | |||||||
| 		return $csv; | 		return $csv; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Database $database | ||||||
|  | 	 * @param string $csv | ||||||
|  | 	 */ | ||||||
| 	private function add_alias_csv(Database $database, /*string*/ $csv) { | 	private function add_alias_csv(Database $database, /*string*/ $csv) { | ||||||
| 		$csv = str_replace("\r", "\n", $csv); | 		$csv = str_replace("\r", "\n", $csv); | ||||||
| 		foreach(explode("\n", $csv) as $line) { | 		foreach(explode("\n", $csv) as $line) { | ||||||
| @ -148,9 +162,15 @@ class AliasEditor extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// add alias *after* mass tag editing, else the MTE will
 | 	/** | ||||||
| 	// search for the images and be redirected to the alias,
 | 	 * Get the priority for this extension. | ||||||
| 	// missing out the images tagged with the oldtag
 | 	 * | ||||||
|  | 	 * Add alias *after* mass tag editing, else the MTE will | ||||||
|  | 	 * search for the images and be redirected to the alias, | ||||||
|  | 	 * missing out the images tagged with the old tag. | ||||||
|  | 	 * | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	public function get_priority() {return 60;} | 	public function get_priority() {return 60;} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,11 +1,14 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class AliasEditorTheme extends Themelet { | class AliasEditorTheme extends Themelet { | ||||||
| 	/* | 	/** | ||||||
| 	 * Show a page of aliases: | 	 * Show a page of aliases. | ||||||
| 	 * | 	 * | ||||||
| 	 * $aliases = an array of ($old_tag => $new_tag) | 	 * Note: $can_manage = whether things like "add new alias" should be shown | ||||||
| 	 * $can_manage = whether things like "add new alias" should be shown | 	 * | ||||||
|  | 	 * @param array $aliases An array of ($old_tag => $new_tag) | ||||||
|  | 	 * @param int $pageNumber | ||||||
|  | 	 * @param int $totalPages | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_aliases($aliases, $pageNumber, $totalPages) { | 	public function display_aliases($aliases, $pageNumber, $totalPages) { | ||||||
| 		global $page, $user; | 		global $page, $user; | ||||||
|  | |||||||
| @ -9,14 +9,22 @@ | |||||||
|  *  Simply enable this extention in the extention manager to enable arrow key navigation. |  *  Simply enable this extention in the extention manager to enable arrow key navigation. | ||||||
|  */ |  */ | ||||||
| class ArrowkeyNavigation extends Extension { | class ArrowkeyNavigation extends Extension { | ||||||
| 	# Adds functionality for post/view on images
 | 	/** | ||||||
|  | 	 * Adds functionality for post/view on images. | ||||||
|  | 	 * | ||||||
|  | 	 * @param DisplayingImageEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onDisplayingImage(DisplayingImageEvent $event) { | 	public function onDisplayingImage(DisplayingImageEvent $event) { | ||||||
| 		$prev_url = make_http(make_link("post/prev/".$event->image->id)); | 		$prev_url = make_http(make_link("post/prev/".$event->image->id)); | ||||||
| 		$next_url = make_http(make_link("post/next/".$event->image->id)); | 		$next_url = make_http(make_link("post/next/".$event->image->id)); | ||||||
| 		$this->add_arrowkeys_code($prev_url, $next_url); | 		$this->add_arrowkeys_code($prev_url, $next_url); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	# Adds functionality for post/list
 | 	/** | ||||||
|  | 	 * Adds functionality for post/list. | ||||||
|  | 	 * | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		if($event->page_matches("post/list")) { | 		if($event->page_matches("post/list")) { | ||||||
| 			$pageinfo = $this->get_list_pageinfo($event); | 			$pageinfo = $this->get_list_pageinfo($event); | ||||||
| @ -26,7 +34,12 @@ class ArrowkeyNavigation extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	# adds the javascript to the page with the given urls
 | 	/** | ||||||
|  | 	 * Adds the javascript to the page with the given urls. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $prev_url | ||||||
|  | 	 * @param string $next_url | ||||||
|  | 	 */ | ||||||
| 	private function add_arrowkeys_code($prev_url, $next_url) { | 	private function add_arrowkeys_code($prev_url, $next_url) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 
 | 
 | ||||||
| @ -41,8 +54,13 @@ class ArrowkeyNavigation extends Extension { | |||||||
| 			</script>", 60);
 | 			</script>", 60);
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	# returns info about the current page number
 | 	/** | ||||||
| 	private function get_list_pageinfo($event) { | 	 * Returns info about the current page number. | ||||||
|  | 	 * | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
|  | 	private function get_list_pageinfo(PageRequestEvent $event) { | ||||||
| 		global $config, $database; | 		global $config, $database; | ||||||
| 
 | 
 | ||||||
| 		// get the amount of images per page
 | 		// get the amount of images per page
 | ||||||
|  | |||||||
| @ -9,8 +9,18 @@ | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class AuthorSetEvent extends Event { | class AuthorSetEvent extends Event { | ||||||
|     var $image, $user, $author; | 	/** @var \Image  */ | ||||||
|  | 	public $image; | ||||||
|  | 	/** @var \User  */ | ||||||
|  | 	public $user; | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $author; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param User $user | ||||||
|  | 	 * @param string $author | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Image $image, User $user, /*string*/ $author) | 	public function __construct(Image $image, User $user, /*string*/ $author) | ||||||
|     { |     { | ||||||
|         $this->image = $image; |         $this->image = $image; | ||||||
| @ -937,8 +947,11 @@ class Artists extends Extension { | |||||||
|         return $result; |         return $result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	* HERE WE GET THE ID OF THE ARTIST | 	 * HERE WE GET THE ID OF THE ARTIST. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @return string|int | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_artist_id($name){ | 	private function get_artist_id($name){ | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -1203,7 +1216,8 @@ class Artists extends Extension { | |||||||
| 	/* | 	/* | ||||||
| 	* HERE WE GET THE INFO OF THE ALIAS | 	* HERE WE GET THE INFO OF THE ALIAS | ||||||
| 	*/ | 	*/ | ||||||
| 	private function get_alias($artistID){ | 	private function get_alias($artistID) | ||||||
|  | 	{ | ||||||
|             if (!is_numeric($artistID)) return; |             if (!is_numeric($artistID)) return; | ||||||
| 
 | 
 | ||||||
|             global $database; |             global $database; | ||||||
|  | |||||||
| @ -1,6 +1,10 @@ | |||||||
| <?php | <?php | ||||||
| class ArtistsTheme extends Themelet { | class ArtistsTheme extends Themelet { | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $author | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function get_author_editor_html(/*string*/ $author) { | 	public function get_author_editor_html(/*string*/ $author) { | ||||||
| 		$h_author = html_escape($author); | 		$h_author = html_escape($author); | ||||||
| 		return " | 		return " | ||||||
| @ -14,6 +18,11 @@ class ArtistsTheme extends Themelet { | |||||||
| 		";
 | 		";
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $mode | ||||||
|  | 	 * @param null|int $artistID | ||||||
|  | 	 * @param bool $is_admin | ||||||
|  | 	 */ | ||||||
| 	public function sidebar_options(/*string*/ $mode, $artistID=NULL, $is_admin=FALSE){ | 	public function sidebar_options(/*string*/ $mode, $artistID=NULL, $is_admin=FALSE){ | ||||||
| 		global $page, $user; | 		global $page, $user; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -69,24 +69,27 @@ xanax | |||||||
| 		$sb = new SetupBlock("Banned Phrases"); | 		$sb = new SetupBlock("Banned Phrases"); | ||||||
| 		$sb->add_label("One per line, lines that start with slashes are treated as regex<br/>"); | 		$sb->add_label("One per line, lines that start with slashes are treated as regex<br/>"); | ||||||
| 		$sb->add_longtext_option("banned_words"); | 		$sb->add_longtext_option("banned_words"); | ||||||
|  | 		$failed = array(); | ||||||
|  | 		foreach($this->get_words() as $word) { | ||||||
|  | 			if($word[0] == '/') { | ||||||
|  | 				if(preg_match($word, "") === false) { | ||||||
|  | 					$failed[] = $word; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if($failed) { | ||||||
|  | 			$sb->add_label("Failed regexes: ".join(", ", $failed)); | ||||||
|  | 		} | ||||||
| 		$event->panel->add_block($sb); | 		$event->panel->add_block($sb); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private function test_text($comment, $ex) { | 	private function test_text($comment, $ex) { | ||||||
| 		global $config; |  | ||||||
| 
 |  | ||||||
| 		$banned = $config->get_string("banned_words"); |  | ||||||
| 		$comment = strtolower($comment); | 		$comment = strtolower($comment); | ||||||
| 
 | 
 | ||||||
| 		foreach(explode("\n", $banned) as $word) { | 		foreach($this->get_words() as $word) { | ||||||
| 			$word = trim(strtolower($word)); | 			if($word[0] == '/') { | ||||||
| 			if(strlen($word) == 0) { |  | ||||||
| 				// line is blank
 |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			else if($word[0] == '/') { |  | ||||||
| 				// lines that start with slash are regex
 | 				// lines that start with slash are regex
 | ||||||
| 				if(preg_match($word, $comment)) { | 				if(preg_match($word, $comment) === 1) { | ||||||
| 					throw $ex; | 					throw $ex; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -99,6 +102,23 @@ xanax | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private function get_words() { | ||||||
|  | 		global $config; | ||||||
|  | 		$words = array(); | ||||||
|  | 
 | ||||||
|  | 		$banned = $config->get_string("banned_words"); | ||||||
|  | 		foreach(explode("\n", $banned) as $word) { | ||||||
|  | 			$word = trim(strtolower($word)); | ||||||
|  | 			if(strlen($word) == 0) { | ||||||
|  | 				// line is blank
 | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			$words[] = $word; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return $words; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public function get_priority() {return 30;} | 	public function get_priority() {return 30;} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -26,6 +26,10 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class BBCode extends FormatterExtension { | class BBCode extends FormatterExtension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function format(/*string*/ $text) { | 	public function format(/*string*/ $text) { | ||||||
| 		$text = $this->extract_code($text); | 		$text = $this->extract_code($text); | ||||||
| 		foreach(array( | 		foreach(array( | ||||||
| @ -35,6 +39,7 @@ class BBCode extends FormatterExtension { | |||||||
| 		} | 		} | ||||||
| 		$text = preg_replace('!^>>([^\d].+)!', '<blockquote><small>$1</small></blockquote>', $text); | 		$text = preg_replace('!^>>([^\d].+)!', '<blockquote><small>$1</small></blockquote>', $text); | ||||||
| 		$text = preg_replace('!>>(\d+)(#c?\d+)?!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('post/view/$1$2').'">>>$1$2</a>', $text); | 		$text = preg_replace('!>>(\d+)(#c?\d+)?!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('post/view/$1$2').'">>>$1$2</a>', $text); | ||||||
|  | 		$text = preg_replace('!\[anchor=(.*?)\](.*?)\[/anchor\]!s', '<span class="anchor">$2 <a class="alink" href="#bb-$1" name="bb-$1" title="link to this anchor"> ¶ </a></span>', $text);  // add "bb-" to avoid clashing with eg #top
 | ||||||
| 		$text = preg_replace('!\[url=site://(.*?)(#c\d+)?\](.*?)\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$3</a>', $text); | 		$text = preg_replace('!\[url=site://(.*?)(#c\d+)?\](.*?)\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$3</a>', $text); | ||||||
| 		$text = preg_replace('!\[url\]site://(.*?)(#c\d+)?\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$1$2</a>', $text); | 		$text = preg_replace('!\[url\]site://(.*?)(#c\d+)?\[/url\]!s', '<a class="shm-clink" data-clink-sel="$2" href="'.make_link('$1$2').'">$1$2</a>', $text); | ||||||
| 		$text = preg_replace('!\[url=((?:https?|ftp|irc|mailto)://.*?)\](.*?)\[/url\]!s', '<a href="$1">$2</a>', $text); | 		$text = preg_replace('!\[url=((?:https?|ftp|irc|mailto)://.*?)\](.*?)\[/url\]!s', '<a href="$1">$2</a>', $text); | ||||||
| @ -62,6 +67,10 @@ class BBCode extends FormatterExtension { | |||||||
| 		return $text; | 		return $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function strip(/*string*/ $text) { | 	public function strip(/*string*/ $text) { | ||||||
| 		foreach(array( | 		foreach(array( | ||||||
| 			"b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", | 			"b", "i", "u", "s", "sup", "sub", "h1", "h2", "h3", "h4", | ||||||
| @ -69,6 +78,7 @@ class BBCode extends FormatterExtension { | |||||||
| 		) as $el) { | 		) as $el) { | ||||||
| 			$text = preg_replace("!\[$el\](.*?)\[/$el\]!s", '$1', $text); | 			$text = preg_replace("!\[$el\](.*?)\[/$el\]!s", '$1', $text); | ||||||
| 		} | 		} | ||||||
|  | 		$text = preg_replace("!\[anchor=(.*?)\](.*?)\[/anchor\]!s", '$2', $text); | ||||||
| 		$text = preg_replace("!\[url=(.*?)\](.*?)\[/url\]!s", '$2', $text); | 		$text = preg_replace("!\[url=(.*?)\](.*?)\[/url\]!s", '$2', $text); | ||||||
| 		$text = preg_replace("!\[img\](.*?)\[/img\]!s", "", $text); | 		$text = preg_replace("!\[img\](.*?)\[/img\]!s", "", $text); | ||||||
| 		$text = preg_replace("!\[\[([^\|\]]+)\|([^\]]+)\]\]!s", '$2', $text); | 		$text = preg_replace("!\[\[([^\|\]]+)\|([^\]]+)\]\]!s", '$2', $text); | ||||||
| @ -81,7 +91,10 @@ class BBCode extends FormatterExtension { | |||||||
| 		return $text; | 		return $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return mixed | ||||||
|  | 	 */ | ||||||
| 	private function filter_spoiler(/*string*/ $text) { | 	private function filter_spoiler(/*string*/ $text) { | ||||||
| 		return str_replace( | 		return str_replace( | ||||||
| 			array("[spoiler]","[/spoiler]"), | 			array("[spoiler]","[/spoiler]"), | ||||||
| @ -89,6 +102,10 @@ class BBCode extends FormatterExtension { | |||||||
| 			$text); | 			$text); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function strip_spoiler(/*string*/ $text) { | 	private function strip_spoiler(/*string*/ $text) { | ||||||
| 		$l1 = strlen("[spoiler]"); | 		$l1 = strlen("[spoiler]"); | ||||||
| 		$l2 = strlen("[/spoiler]"); | 		$l2 = strlen("[/spoiler]"); | ||||||
| @ -110,6 +127,10 @@ class BBCode extends FormatterExtension { | |||||||
| 		return $text; | 		return $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function extract_code(/*string*/ $text) { | 	private function extract_code(/*string*/ $text) { | ||||||
| 		# at the end of this function, the only code! blocks should be
 | 		# at the end of this function, the only code! blocks should be
 | ||||||
| 		# the ones we've added -- others may contain malicious content,
 | 		# the ones we've added -- others may contain malicious content,
 | ||||||
| @ -137,6 +158,10 @@ class BBCode extends FormatterExtension { | |||||||
| 		return $text; | 		return $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function insert_code(/*string*/ $text) { | 	private function insert_code(/*string*/ $text) { | ||||||
| 		$l1 = strlen("[code!]"); | 		$l1 = strlen("[code!]"); | ||||||
| 		$l2 = strlen("[/code!]"); | 		$l2 = strlen("[/code!]"); | ||||||
|  | |||||||
| @ -8,3 +8,9 @@ BLOCKQUOTE { | |||||||
| 	padding: 8px; | 	padding: 8px; | ||||||
| 	background: #DDD; | 	background: #DDD; | ||||||
| } | } | ||||||
|  | .anchor A.alink { | ||||||
|  | 	visibility: hidden; | ||||||
|  | } | ||||||
|  | .anchor:hover A.alink { | ||||||
|  | 	visibility: visible; | ||||||
|  | } | ||||||
|  | |||||||
| @ -71,6 +71,12 @@ class BBCodeUnitTest extends UnitTestCase { | |||||||
| 			"<a href=\"mailto:spam@shishnet.org\">spam@shishnet.org</a>"); | 			"<a href=\"mailto:spam@shishnet.org\">spam@shishnet.org</a>"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public function testAnchor() { | ||||||
|  | 		$this->assertEqual( | ||||||
|  | 			$this->filter("[anchor=rules]Rules[/anchor]"), | ||||||
|  | 			'<span class="anchor">Rules <a class="alink" href="#bb-rules" name="bb-rules" title="link to this anchor"> ¶ </a></span>'); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	private function filter($in) { | 	private function filter($in) { | ||||||
| 		$bb = new BBCode(); | 		$bb = new BBCode(); | ||||||
| 		return $bb->format($in); | 		return $bb->format($in); | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ class Blocks extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		global $config, $database, $page, $user; | 		global $database, $page, $user; | ||||||
| 
 | 
 | ||||||
| 		$blocks = $database->cache->get("blocks"); | 		$blocks = $database->cache->get("blocks"); | ||||||
| 		if($blocks === false) { | 		if($blocks === false) { | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ $kioskMode = false; | |||||||
| 
 | 
 | ||||||
| include '../php/filestorage.class.php'; | include '../php/filestorage.class.php'; | ||||||
| include '../preferences.php'; | include '../preferences.php'; | ||||||
| include '../php/json.class.php'; |  | ||||||
| include '../php/functions.php'; | include '../php/functions.php'; | ||||||
| include '../php/yshout.class.php'; | include '../php/yshout.class.php'; | ||||||
| include '../php/ajaxcall.class.php'; | include '../php/ajaxcall.class.php'; | ||||||
| @ -41,7 +40,7 @@ function doLogin() { | |||||||
| 			'html' => cp() | 			'html' => cp() | ||||||
| 		); | 		); | ||||||
| 		 | 		 | ||||||
| 		echo jsonEncode($result); | 		echo json_encode($result); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| @ -53,7 +52,7 @@ function doLogin() { | |||||||
| 	} else | 	} else | ||||||
| 		$result['error'] = 'invalid'; | 		$result['error'] = 'invalid'; | ||||||
| 
 | 
 | ||||||
| 	echo jsonEncode($result); | 	echo json_encode($result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function doLogout() { | function doLogout() { | ||||||
| @ -63,7 +62,7 @@ function doLogout() { | |||||||
| 		'error' => false | 		'error' => false | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	echo jsonEncode($result); | 	echo json_encode($result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function doUnban() { | function doUnban() { | ||||||
| @ -74,7 +73,7 @@ function doUnban() { | |||||||
| 			'error' => false | 			'error' => false | ||||||
| 		); | 		); | ||||||
| 		 | 		 | ||||||
| 		echo jsonEncode($result); | 		echo json_encode($result); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| @ -92,7 +91,7 @@ function doUnban() { | |||||||
| 		$result['error'] = 'notbanned'; | 		$result['error'] = 'notbanned'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	echo jsonEncode($result); | 	echo json_encode($result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function doUnbanAll() { | function doUnbanAll() { | ||||||
| @ -103,7 +102,7 @@ function doUnbanAll() { | |||||||
| 			'error' => false | 			'error' => false | ||||||
| 		); | 		); | ||||||
| 		 | 		 | ||||||
| 		echo jsonEncode($result); | 		echo json_encode($result); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| @ -116,7 +115,7 @@ function doUnbanAll() { | |||||||
| 		'error' => false | 		'error' => false | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	echo jsonEncode($result); | 	echo json_encode($result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -128,7 +127,7 @@ function doSetPreference() { | |||||||
| 			'error' => false | 			'error' => false | ||||||
| 		); | 		); | ||||||
| 		 | 		 | ||||||
| 		echo jsonEncode($result); | 		echo json_encode($result); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| @ -150,7 +149,7 @@ function doSetPreference() { | |||||||
| 		'error' => false | 		'error' => false | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	echo jsonEncode($result); | 	echo json_encode($result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -162,7 +161,7 @@ function doResetPreferences() { | |||||||
| 			'error' => false | 			'error' => false | ||||||
| 		); | 		); | ||||||
| 		 | 		 | ||||||
| 		echo jsonEncode($result); | 		echo json_encode($result); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| @ -177,7 +176,7 @@ function doResetPreferences() { | |||||||
| 		'prefs' => $prefs | 		'prefs' => $prefs | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	echo jsonEncode($result); | 	echo json_encode($result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* CP Display */ | /* CP Display */ | ||||||
| @ -456,4 +455,3 @@ function about() { | |||||||
| 	return $html; | 	return $html; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ?>
 |  | ||||||
| @ -3,7 +3,6 @@ | |||||||
| 
 | 
 | ||||||
| 	include '../php/filestorage.class.php'; | 	include '../php/filestorage.class.php'; | ||||||
| 	include '../preferences.php'; | 	include '../preferences.php'; | ||||||
| 	include '../php/json.class.php'; |  | ||||||
| 	include '../php/functions.php'; | 	include '../php/functions.php'; | ||||||
| 	include '../php/yshout.class.php'; | 	include '../php/yshout.class.php'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,9 +2,7 @@ | |||||||
| 	$null = null; | 	$null = null; | ||||||
| 	include 'php/filestorage.class.php'; | 	include 'php/filestorage.class.php'; | ||||||
| 	include 'preferences.php'; | 	include 'preferences.php'; | ||||||
| 	include 'php/json.class.php'; |  | ||||||
| 	include 'php/functions.php'; | 	include 'php/functions.php'; | ||||||
| 	include 'php/yshout.class.php'; | 	include 'php/yshout.class.php'; | ||||||
| 	include 'php/ajaxcall.class.php'; | 	include 'php/ajaxcall.class.php'; | ||||||
| 
 | 
 | ||||||
| ?>
 |  | ||||||
| @ -95,7 +95,7 @@ | |||||||
| 					$send['error'] = false; | 					$send['error'] = false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		function doUnban() { | 		function doUnban() { | ||||||
| @ -115,7 +115,7 @@ | |||||||
| 					$send['error'] = false; | 					$send['error'] = false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		function doDelete() { | 		function doDelete() { | ||||||
| @ -132,7 +132,7 @@ | |||||||
| 					$send['error'] = false; | 					$send['error'] = false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		function banSelf() { | 		function banSelf() { | ||||||
| @ -143,7 +143,7 @@ | |||||||
| 			$send = array(); | 			$send = array(); | ||||||
| 			$send['error'] = false; | 			$send['error'] = false; | ||||||
| 			 | 			 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		function unbanSelf() { | 		function unbanSelf() { | ||||||
| @ -158,7 +158,7 @@ | |||||||
| 				$send['error'] = 'admin'; | 				$send['error'] = 'admin'; | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		function reload() { | 		function reload() { | ||||||
| @ -168,7 +168,7 @@ | |||||||
| 			$posts = $ys->latestPosts($prefs['truncate']); | 			$posts = $ys->latestPosts($prefs['truncate']); | ||||||
| 			$this->setSessTimestamp($posts); | 			$this->setSessTimestamp($posts); | ||||||
| 			$this->updates['posts'] = $posts;						 | 			$this->updates['posts'] = $posts;						 | ||||||
| 			echo jsonEncode($this->updates); | 			echo json_encode($this->updates); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		function initSession() { | 		function initSession() { | ||||||
| @ -186,7 +186,7 @@ | |||||||
| 				'banned' => true | 				'banned' => true | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($this->updates); | 			echo json_encode($this->updates); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		function sendUpdates() { | 		function sendUpdates() { | ||||||
| @ -199,7 +199,7 @@ | |||||||
| 
 | 
 | ||||||
| 			$this->updates['posts'] = $posts; | 			$this->updates['posts'] = $posts; | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($this->updates); | 			echo json_encode($this->updates); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		function setSessTimestamp(&$posts) { | 		function setSessTimestamp(&$posts) { | ||||||
| @ -231,7 +231,7 @@ | |||||||
| 			if ($ys->banned(ip())) | 			if ($ys->banned(ip())) | ||||||
| 				$this->updates['banned'] = true; | 				$this->updates['banned'] = true; | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($this->updates); | 			echo json_encode($this->updates); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		function cleanPrefs($prefs) { | 		function cleanPrefs($prefs) { | ||||||
| @ -253,7 +253,7 @@ | |||||||
| 					$send['error'] = false; | 					$send['error'] = false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		function clearLogs() { | 		function clearLogs() { | ||||||
| @ -277,7 +277,7 @@ | |||||||
| 					$send['error'] = false; | 					$send['error'] = false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			echo jsonEncode($send); | 			echo json_encode($send); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -45,19 +45,6 @@ | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	function jsonEncode(&$array) { |  | ||||||
| 		if ($array) { |  | ||||||
| 			$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |  | ||||||
| 			return $json->encode($array); |  | ||||||
| 		} else |  | ||||||
| 			return 'ar'; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	function jsonDecode($encoded) { |  | ||||||
| 		$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |  | ||||||
| 		return $json->decode($encoded); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	function validIP($ip) { | 	function validIP($ip) { | ||||||
| 		if ($ip == long2ip(ip2long($ip))) | 		if ($ip == long2ip(ip2long($ip))) | ||||||
| 			return true; | 			return true; | ||||||
|  | |||||||
| @ -1,805 +0,0 @@ | |||||||
| <?php |  | ||||||
| /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Converts to and from JSON format. |  | ||||||
| * |  | ||||||
| * JSON (JavaScript Object Notation) is a lightweight data-interchange |  | ||||||
| * format. It is easy for humans to read and write. It is easy for machines |  | ||||||
| * to parse and generate. It is based on a subset of the JavaScript |  | ||||||
| * Programming Language, Standard ECMA-262 3rd Edition - December 1999. |  | ||||||
| * This feature can also be found in  Python. JSON is a text format that is |  | ||||||
| * completely language independent but uses conventions that are familiar |  | ||||||
| * to programmers of the C-family of languages, including C, C++, C#, Java,
 |  | ||||||
| * JavaScript, Perl, TCL, and many others. These properties make JSON an |  | ||||||
| * ideal data-interchange language. |  | ||||||
| * |  | ||||||
| * This package provides a simple encoder and decoder for JSON notation. It |  | ||||||
| * is intended for use with client-side Javascript applications that make |  | ||||||
| * use of HTTPRequest to perform server communication functions - data can |  | ||||||
| * be encoded into JSON notation for use in a client-side javascript, or |  | ||||||
| * decoded from incoming Javascript requests. JSON format is native to |  | ||||||
| * Javascript, and can be directly eval()'ed with no further parsing |  | ||||||
| * overhead |  | ||||||
| * |  | ||||||
| * All strings should be in ASCII or UTF-8 format! |  | ||||||
| * |  | ||||||
| * LICENSE: Redistribution and use in source and binary forms, with or |  | ||||||
| * without modification, are permitted provided that the following |  | ||||||
| * conditions are met: Redistributions of source code must retain the |  | ||||||
| * above copyright notice, this list of conditions and the following |  | ||||||
| * disclaimer. Redistributions in binary form must reproduce the above |  | ||||||
| * copyright notice, this list of conditions and the following disclaimer |  | ||||||
| * in the documentation and/or other materials provided with the |  | ||||||
| * distribution. |  | ||||||
| * |  | ||||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |  | ||||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |  | ||||||
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |  | ||||||
| * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |  | ||||||
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |  | ||||||
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |  | ||||||
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |  | ||||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |  | ||||||
| * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |  | ||||||
| * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |  | ||||||
| * DAMAGE. |  | ||||||
| * |  | ||||||
| * @category |  | ||||||
| * @package     Services_JSON |  | ||||||
| * @author      Michal Migurski <mike-json@teczno.com> |  | ||||||
| * @author      Matt Knapp <mdknapp[at]gmail[dot]com> |  | ||||||
| * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |  | ||||||
| * @copyright   2005 Michal Migurski |  | ||||||
| * @version     CVS: $Id: JSON.php,v 1.30 2006/03/08 16:10:20 migurski Exp $ |  | ||||||
| * @license     http://www.opensource.org/licenses/bsd-license.php |  | ||||||
| * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Marker constant for Services_JSON::decode(), used to flag stack state |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_SLICE',   1); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Marker constant for Services_JSON::decode(), used to flag stack state |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_IN_STR',  2); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Marker constant for Services_JSON::decode(), used to flag stack state |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_IN_ARR',  3); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Marker constant for Services_JSON::decode(), used to flag stack state |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_IN_OBJ',  4); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Marker constant for Services_JSON::decode(), used to flag stack state |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_IN_CMT', 5); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Behavior switch for Services_JSON::decode() |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_LOOSE_TYPE', 16); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Behavior switch for Services_JSON::decode() |  | ||||||
| */ |  | ||||||
| define('SERVICES_JSON_SUPPRESS_ERRORS', 32); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
| * Converts to and from JSON format. |  | ||||||
| * |  | ||||||
| * Brief example of use: |  | ||||||
| * |  | ||||||
| * <code> |  | ||||||
| * // create a new instance of Services_JSON
 |  | ||||||
| * $json = new Services_JSON(); |  | ||||||
| * |  | ||||||
| * // convert a complexe value to JSON notation, and send it to the browser
 |  | ||||||
| * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); |  | ||||||
| * $output = $json->encode($value); |  | ||||||
| * |  | ||||||
| * print($output); |  | ||||||
| * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
 |  | ||||||
| * |  | ||||||
| * // accept incoming POST data, assumed to be in JSON notation
 |  | ||||||
| * $input = file_get_contents('php://input', 1000000); |  | ||||||
| * $value = $json->decode($input); |  | ||||||
| * </code> |  | ||||||
| */ |  | ||||||
| class Services_JSON |  | ||||||
| { |  | ||||||
|    /** |  | ||||||
|     * constructs a new JSON instance |  | ||||||
|     * |  | ||||||
|     * @param    int     $use    object behavior flags; combine with boolean-OR |  | ||||||
|     * |  | ||||||
|     *                           possible values: |  | ||||||
|     *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing. |  | ||||||
|     *                                   "{...}" syntax creates associative arrays |  | ||||||
|     *                                   instead of objects in decode(). |  | ||||||
|     *                           - SERVICES_JSON_SUPPRESS_ERRORS:  error suppression. |  | ||||||
|     *                                   Values which can't be encoded (e.g. resources) |  | ||||||
|     *                                   appear as NULL instead of throwing errors. |  | ||||||
|     *                                   By default, a deeply-nested resource will |  | ||||||
|     *                                   bubble up with an error, so all return values |  | ||||||
|     *                                   from encode() should be checked with isError() |  | ||||||
|     */ |  | ||||||
|     function Services_JSON($use = 0) |  | ||||||
|     { |  | ||||||
|         $this->use = $use; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|    /** |  | ||||||
|     * convert a string from one UTF-16 char to one UTF-8 char |  | ||||||
|     * |  | ||||||
|     * Normally should be handled by mb_convert_encoding, but |  | ||||||
|     * provides a slower PHP-only method for installations |  | ||||||
|     * that lack the multibye string extension. |  | ||||||
|     * |  | ||||||
|     * @param    string  $utf16  UTF-16 character |  | ||||||
|     * @return   string  UTF-8 character |  | ||||||
|     * @access   private |  | ||||||
|     */ |  | ||||||
|     function utf162utf8($utf16) |  | ||||||
|     { |  | ||||||
|         // oh please oh please oh please oh please oh please
 |  | ||||||
|         if(function_exists('mb_convert_encoding')) { |  | ||||||
|             return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); |  | ||||||
| 
 |  | ||||||
|         switch(true) { |  | ||||||
|             case ((0x7F & $bytes) == $bytes): |  | ||||||
|                 // this case should never be reached, because we are in ASCII range
 |  | ||||||
|                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                 return chr(0x7F & $bytes); |  | ||||||
| 
 |  | ||||||
|             case (0x07FF & $bytes) == $bytes: |  | ||||||
|                 // return a 2-byte UTF-8 character
 |  | ||||||
|                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                 return chr(0xC0 | (($bytes >> 6) & 0x1F)) |  | ||||||
|                      . chr(0x80 | ($bytes & 0x3F)); |  | ||||||
| 
 |  | ||||||
|             case (0xFFFF & $bytes) == $bytes: |  | ||||||
|                 // return a 3-byte UTF-8 character
 |  | ||||||
|                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                 return chr(0xE0 | (($bytes >> 12) & 0x0F)) |  | ||||||
|                      . chr(0x80 | (($bytes >> 6) & 0x3F)) |  | ||||||
|                      . chr(0x80 | ($bytes & 0x3F)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // ignoring UTF-32 for now, sorry
 |  | ||||||
|         return ''; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|    /** |  | ||||||
|     * convert a string from one UTF-8 char to one UTF-16 char |  | ||||||
|     * |  | ||||||
|     * Normally should be handled by mb_convert_encoding, but |  | ||||||
|     * provides a slower PHP-only method for installations |  | ||||||
|     * that lack the multibye string extension. |  | ||||||
|     * |  | ||||||
|     * @param    string  $utf8   UTF-8 character |  | ||||||
|     * @return   string  UTF-16 character |  | ||||||
|     * @access   private |  | ||||||
|     */ |  | ||||||
|     function utf82utf16($utf8) |  | ||||||
|     { |  | ||||||
|         // oh please oh please oh please oh please oh please
 |  | ||||||
|         if(function_exists('mb_convert_encoding')) { |  | ||||||
|             return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         switch(strlen($utf8)) { |  | ||||||
|             case 1: |  | ||||||
|                 // this case should never be reached, because we are in ASCII range
 |  | ||||||
|                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                 return $utf8; |  | ||||||
| 
 |  | ||||||
|             case 2: |  | ||||||
|                 // return a UTF-16 character from a 2-byte UTF-8 char
 |  | ||||||
|                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                 return chr(0x07 & (ord($utf8{0}) >> 2)) |  | ||||||
|                      . chr((0xC0 & (ord($utf8{0}) << 6)) |  | ||||||
|                          | (0x3F & ord($utf8{1}))); |  | ||||||
| 
 |  | ||||||
|             case 3: |  | ||||||
|                 // return a UTF-16 character from a 3-byte UTF-8 char
 |  | ||||||
|                 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                 return chr((0xF0 & (ord($utf8{0}) << 4)) |  | ||||||
|                          | (0x0F & (ord($utf8{1}) >> 2))) |  | ||||||
|                      . chr((0xC0 & (ord($utf8{1}) << 6)) |  | ||||||
|                          | (0x7F & ord($utf8{2}))); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // ignoring UTF-32 for now, sorry
 |  | ||||||
|         return ''; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|    /** |  | ||||||
|     * encodes an arbitrary variable into JSON format |  | ||||||
|     * |  | ||||||
|     * @param    mixed   $var    any number, boolean, string, array, or object to be encoded. |  | ||||||
|     *                           see argument 1 to Services_JSON() above for array-parsing behavior. |  | ||||||
|     *                           if var is a strng, note that encode() always expects it |  | ||||||
|     *                           to be in ASCII or UTF-8 format! |  | ||||||
|     * |  | ||||||
|     * @return   mixed   JSON string representation of input var or an error if a problem occurs |  | ||||||
|     * @access   public |  | ||||||
|     */ |  | ||||||
|     function encode($var) |  | ||||||
|     { |  | ||||||
|         switch (gettype($var)) { |  | ||||||
|             case 'boolean': |  | ||||||
|                 return $var ? 'true' : 'false'; |  | ||||||
| 
 |  | ||||||
|             case 'NULL': |  | ||||||
|                 return 'null'; |  | ||||||
| 
 |  | ||||||
|             case 'integer': |  | ||||||
|                 return (int) $var; |  | ||||||
| 
 |  | ||||||
|             case 'double': |  | ||||||
|             case 'float': |  | ||||||
|                 return (float) $var; |  | ||||||
| 
 |  | ||||||
|             case 'string': |  | ||||||
|                 // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
 |  | ||||||
|                 $ascii = ''; |  | ||||||
|                 $strlen_var = strlen($var); |  | ||||||
| 
 |  | ||||||
|                /* |  | ||||||
|                 * Iterate over every character in the string, |  | ||||||
|                 * escaping with a slash or encoding to UTF-8 where necessary |  | ||||||
|                 */ |  | ||||||
|                 for ($c = 0; $c < $strlen_var; ++$c) { |  | ||||||
| 
 |  | ||||||
|                     $ord_var_c = ord($var{$c}); |  | ||||||
| 
 |  | ||||||
|                     switch (true) { |  | ||||||
|                         case $ord_var_c == 0x08: |  | ||||||
|                             $ascii .= '\b'; |  | ||||||
|                             break; |  | ||||||
|                         case $ord_var_c == 0x09: |  | ||||||
|                             $ascii .= '\t'; |  | ||||||
|                             break; |  | ||||||
|                         case $ord_var_c == 0x0A: |  | ||||||
|                             $ascii .= '\n'; |  | ||||||
|                             break; |  | ||||||
|                         case $ord_var_c == 0x0C: |  | ||||||
|                             $ascii .= '\f'; |  | ||||||
|                             break; |  | ||||||
|                         case $ord_var_c == 0x0D: |  | ||||||
|                             $ascii .= '\r'; |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case $ord_var_c == 0x22: |  | ||||||
|                         case $ord_var_c == 0x2F: |  | ||||||
|                         case $ord_var_c == 0x5C: |  | ||||||
|                             // double quote, slash, slosh
 |  | ||||||
|                             $ascii .= '\\'.$var{$c}; |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): |  | ||||||
|                             // characters U-00000000 - U-0000007F (same as ASCII)
 |  | ||||||
|                             $ascii .= $var{$c}; |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case (($ord_var_c & 0xE0) == 0xC0): |  | ||||||
|                             // characters U-00000080 - U-000007FF, mask 110XXXXX
 |  | ||||||
|                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                             $char = pack('C*', $ord_var_c, ord($var{$c + 1})); |  | ||||||
|                             $c += 1; |  | ||||||
|                             $utf16 = $this->utf82utf16($char); |  | ||||||
|                             $ascii .= sprintf('\u%04s', bin2hex($utf16)); |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case (($ord_var_c & 0xF0) == 0xE0): |  | ||||||
|                             // characters U-00000800 - U-0000FFFF, mask 1110XXXX
 |  | ||||||
|                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                             $char = pack('C*', $ord_var_c, |  | ||||||
|                                          ord($var{$c + 1}), |  | ||||||
|                                          ord($var{$c + 2})); |  | ||||||
|                             $c += 2; |  | ||||||
|                             $utf16 = $this->utf82utf16($char); |  | ||||||
|                             $ascii .= sprintf('\u%04s', bin2hex($utf16)); |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case (($ord_var_c & 0xF8) == 0xF0): |  | ||||||
|                             // characters U-00010000 - U-001FFFFF, mask 11110XXX
 |  | ||||||
|                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                             $char = pack('C*', $ord_var_c, |  | ||||||
|                                          ord($var{$c + 1}), |  | ||||||
|                                          ord($var{$c + 2}), |  | ||||||
|                                          ord($var{$c + 3})); |  | ||||||
|                             $c += 3; |  | ||||||
|                             $utf16 = $this->utf82utf16($char); |  | ||||||
|                             $ascii .= sprintf('\u%04s', bin2hex($utf16)); |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case (($ord_var_c & 0xFC) == 0xF8): |  | ||||||
|                             // characters U-00200000 - U-03FFFFFF, mask 111110XX
 |  | ||||||
|                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                             $char = pack('C*', $ord_var_c, |  | ||||||
|                                          ord($var{$c + 1}), |  | ||||||
|                                          ord($var{$c + 2}), |  | ||||||
|                                          ord($var{$c + 3}), |  | ||||||
|                                          ord($var{$c + 4})); |  | ||||||
|                             $c += 4; |  | ||||||
|                             $utf16 = $this->utf82utf16($char); |  | ||||||
|                             $ascii .= sprintf('\u%04s', bin2hex($utf16)); |  | ||||||
|                             break; |  | ||||||
| 
 |  | ||||||
|                         case (($ord_var_c & 0xFE) == 0xFC): |  | ||||||
|                             // characters U-04000000 - U-7FFFFFFF, mask 1111110X
 |  | ||||||
|                             // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                             $char = pack('C*', $ord_var_c, |  | ||||||
|                                          ord($var{$c + 1}), |  | ||||||
|                                          ord($var{$c + 2}), |  | ||||||
|                                          ord($var{$c + 3}), |  | ||||||
|                                          ord($var{$c + 4}), |  | ||||||
|                                          ord($var{$c + 5})); |  | ||||||
|                             $c += 5; |  | ||||||
|                             $utf16 = $this->utf82utf16($char); |  | ||||||
|                             $ascii .= sprintf('\u%04s', bin2hex($utf16)); |  | ||||||
|                             break; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 return '"'.$ascii.'"'; |  | ||||||
| 
 |  | ||||||
|             case 'array': |  | ||||||
|                /* |  | ||||||
|                 * As per JSON spec if any array key is not an integer |  | ||||||
|                 * we must treat the the whole array as an object. We |  | ||||||
|                 * also try to catch a sparsely populated associative |  | ||||||
|                 * array with numeric keys here because some JS engines |  | ||||||
|                 * will create an array with empty indexes up to |  | ||||||
|                 * max_index which can cause memory issues and because |  | ||||||
|                 * the keys, which may be relevant, will be remapped |  | ||||||
|                 * otherwise. |  | ||||||
|                 * |  | ||||||
|                 * As per the ECMA and JSON specification an object may |  | ||||||
|                 * have any string as a property. Unfortunately due to |  | ||||||
|                 * a hole in the ECMA specification if the key is a |  | ||||||
|                 * ECMA reserved word or starts with a digit the |  | ||||||
|                 * parameter is only accessible using ECMAScript's |  | ||||||
|                 * bracket notation. |  | ||||||
|                 */ |  | ||||||
| 
 |  | ||||||
|                 // treat as a JSON object
 |  | ||||||
|                 if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { |  | ||||||
|                     $properties = array_map(array($this, 'name_value'), |  | ||||||
|                                             array_keys($var), |  | ||||||
|                                             array_values($var)); |  | ||||||
| 
 |  | ||||||
|                     foreach($properties as $property) { |  | ||||||
|                         if(Services_JSON::isError($property)) { |  | ||||||
|                             return $property; |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     return '{' . join(',', $properties) . '}'; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // treat it like a regular array
 |  | ||||||
|                 $elements = array_map(array($this, 'encode'), $var); |  | ||||||
| 
 |  | ||||||
|                 foreach($elements as $element) { |  | ||||||
|                     if(Services_JSON::isError($element)) { |  | ||||||
|                         return $element; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 return '[' . join(',', $elements) . ']'; |  | ||||||
| 
 |  | ||||||
|             case 'object': |  | ||||||
|                 $vars = get_object_vars($var); |  | ||||||
| 
 |  | ||||||
|                 $properties = array_map(array($this, 'name_value'), |  | ||||||
|                                         array_keys($vars), |  | ||||||
|                                         array_values($vars)); |  | ||||||
| 
 |  | ||||||
|                 foreach($properties as $property) { |  | ||||||
|                     if(Services_JSON::isError($property)) { |  | ||||||
|                         return $property; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 return '{' . join(',', $properties) . '}'; |  | ||||||
| 
 |  | ||||||
|             default: |  | ||||||
|                 return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) |  | ||||||
|                     ? 'null' |  | ||||||
|                     : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|    /** |  | ||||||
|     * array-walking function for use in generating JSON-formatted name-value pairs |  | ||||||
|     * |  | ||||||
|     * @param    string  $name   name of key to use |  | ||||||
|     * @param    mixed   $value  reference to an array element to be encoded |  | ||||||
|     * |  | ||||||
|     * @return   string  JSON-formatted name-value pair, like '"name":value' |  | ||||||
|     * @access   private |  | ||||||
|     */ |  | ||||||
|     function name_value($name, $value) |  | ||||||
|     { |  | ||||||
|         $encoded_value = $this->encode($value); |  | ||||||
| 
 |  | ||||||
|         if(Services_JSON::isError($encoded_value)) { |  | ||||||
|             return $encoded_value; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return $this->encode(strval($name)) . ':' . $encoded_value; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|    /** |  | ||||||
|     * reduce a string by removing leading and trailing comments and whitespace |  | ||||||
|     * |  | ||||||
|     * @param    $str    string      string value to strip of comments and whitespace |  | ||||||
|     * |  | ||||||
|     * @return   string  string value stripped of comments and whitespace |  | ||||||
|     * @access   private |  | ||||||
|     */ |  | ||||||
|     function reduce_string($str) |  | ||||||
|     { |  | ||||||
|         $str = preg_replace(array( |  | ||||||
| 
 |  | ||||||
|                 // eliminate single line comments in '// ...' form
 |  | ||||||
|                 '#^\s*//(.+)$#m', |  | ||||||
| 
 |  | ||||||
|                 // eliminate multi-line comments in '/* ... */' form, at start of string
 |  | ||||||
|                 '#^\s*/\*(.+)\*/#Us', |  | ||||||
| 
 |  | ||||||
|                 // eliminate multi-line comments in '/* ... */' form, at end of string
 |  | ||||||
|                 '#/\*(.+)\*/\s*$#Us' |  | ||||||
| 
 |  | ||||||
|             ), '', $str); |  | ||||||
| 
 |  | ||||||
|         // eliminate extraneous space
 |  | ||||||
|         return trim($str); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|    /** |  | ||||||
|     * decodes a JSON string into appropriate variable |  | ||||||
|     * |  | ||||||
|     * @param    string  $str    JSON-formatted string |  | ||||||
|     * |  | ||||||
|     * @return   mixed   number, boolean, string, array, or object |  | ||||||
|     *                   corresponding to given JSON input string. |  | ||||||
|     *                   See argument 1 to Services_JSON() above for object-output behavior. |  | ||||||
|     *                   Note that decode() always returns strings |  | ||||||
|     *                   in ASCII or UTF-8 format! |  | ||||||
|     * @access   public |  | ||||||
|     */ |  | ||||||
|     function decode($str) |  | ||||||
|     { |  | ||||||
|         $str = $this->reduce_string($str); |  | ||||||
| 
 |  | ||||||
|         switch (strtolower($str)) { |  | ||||||
|             case 'true': |  | ||||||
|                 return true; |  | ||||||
| 
 |  | ||||||
|             case 'false': |  | ||||||
|                 return false; |  | ||||||
| 
 |  | ||||||
|             case 'null': |  | ||||||
|                 return null; |  | ||||||
| 
 |  | ||||||
|             default: |  | ||||||
|                 $m = array(); |  | ||||||
| 
 |  | ||||||
|                 if (is_numeric($str)) { |  | ||||||
|                     // Lookie-loo, it's a number
 |  | ||||||
| 
 |  | ||||||
|                     // This would work on its own, but I'm trying to be
 |  | ||||||
|                     // good about returning integers where appropriate:
 |  | ||||||
|                     // return (float)$str;
 |  | ||||||
| 
 |  | ||||||
|                     // Return float or int, as appropriate
 |  | ||||||
|                     return ((float)$str == (integer)$str) |  | ||||||
|                         ? (integer)$str |  | ||||||
|                         : (float)$str; |  | ||||||
| 
 |  | ||||||
|                 } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { |  | ||||||
|                     // STRINGS RETURNED IN UTF-8 FORMAT
 |  | ||||||
|                     $delim = substr($str, 0, 1); |  | ||||||
|                     $chrs = substr($str, 1, -1); |  | ||||||
|                     $utf8 = ''; |  | ||||||
|                     $strlen_chrs = strlen($chrs); |  | ||||||
| 
 |  | ||||||
|                     for ($c = 0; $c < $strlen_chrs; ++$c) { |  | ||||||
| 
 |  | ||||||
|                         $substr_chrs_c_2 = substr($chrs, $c, 2); |  | ||||||
|                         $ord_chrs_c = ord($chrs{$c}); |  | ||||||
| 
 |  | ||||||
|                         switch (true) { |  | ||||||
|                             case $substr_chrs_c_2 == '\b': |  | ||||||
|                                 $utf8 .= chr(0x08); |  | ||||||
|                                 ++$c; |  | ||||||
|                                 break; |  | ||||||
|                             case $substr_chrs_c_2 == '\t': |  | ||||||
|                                 $utf8 .= chr(0x09); |  | ||||||
|                                 ++$c; |  | ||||||
|                                 break; |  | ||||||
|                             case $substr_chrs_c_2 == '\n': |  | ||||||
|                                 $utf8 .= chr(0x0A); |  | ||||||
|                                 ++$c; |  | ||||||
|                                 break; |  | ||||||
|                             case $substr_chrs_c_2 == '\f': |  | ||||||
|                                 $utf8 .= chr(0x0C); |  | ||||||
|                                 ++$c; |  | ||||||
|                                 break; |  | ||||||
|                             case $substr_chrs_c_2 == '\r': |  | ||||||
|                                 $utf8 .= chr(0x0D); |  | ||||||
|                                 ++$c; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case $substr_chrs_c_2 == '\\"': |  | ||||||
|                             case $substr_chrs_c_2 == '\\\'': |  | ||||||
|                             case $substr_chrs_c_2 == '\\\\': |  | ||||||
|                             case $substr_chrs_c_2 == '\\/': |  | ||||||
|                                 if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || |  | ||||||
|                                    ($delim == "'" && $substr_chrs_c_2 != '\\"')) { |  | ||||||
|                                     $utf8 .= $chrs{++$c}; |  | ||||||
|                                 } |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): |  | ||||||
|                                 // single, escaped unicode character
 |  | ||||||
|                                 $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |  | ||||||
|                                        . chr(hexdec(substr($chrs, ($c + 4), 2))); |  | ||||||
|                                 $utf8 .= $this->utf162utf8($utf16); |  | ||||||
|                                 $c += 5; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): |  | ||||||
|                                 $utf8 .= $chrs{$c}; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case ($ord_chrs_c & 0xE0) == 0xC0: |  | ||||||
|                                 // characters U-00000080 - U-000007FF, mask 110XXXXX
 |  | ||||||
|                                 //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                                 $utf8 .= substr($chrs, $c, 2); |  | ||||||
|                                 ++$c; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case ($ord_chrs_c & 0xF0) == 0xE0: |  | ||||||
|                                 // characters U-00000800 - U-0000FFFF, mask 1110XXXX
 |  | ||||||
|                                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                                 $utf8 .= substr($chrs, $c, 3); |  | ||||||
|                                 $c += 2; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case ($ord_chrs_c & 0xF8) == 0xF0: |  | ||||||
|                                 // characters U-00010000 - U-001FFFFF, mask 11110XXX
 |  | ||||||
|                                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                                 $utf8 .= substr($chrs, $c, 4); |  | ||||||
|                                 $c += 3; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case ($ord_chrs_c & 0xFC) == 0xF8: |  | ||||||
|                                 // characters U-00200000 - U-03FFFFFF, mask 111110XX
 |  | ||||||
|                                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                                 $utf8 .= substr($chrs, $c, 5); |  | ||||||
|                                 $c += 4; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                             case ($ord_chrs_c & 0xFE) == 0xFC: |  | ||||||
|                                 // characters U-04000000 - U-7FFFFFFF, mask 1111110X
 |  | ||||||
|                                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 |  | ||||||
|                                 $utf8 .= substr($chrs, $c, 6); |  | ||||||
|                                 $c += 5; |  | ||||||
|                                 break; |  | ||||||
| 
 |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     return $utf8; |  | ||||||
| 
 |  | ||||||
|                 } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { |  | ||||||
|                     // array, or object notation
 |  | ||||||
| 
 |  | ||||||
|                     if ($str{0} == '[') { |  | ||||||
|                         $stk = array(SERVICES_JSON_IN_ARR); |  | ||||||
|                         $arr = array(); |  | ||||||
|                     } else { |  | ||||||
|                         if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |  | ||||||
|                             $stk = array(SERVICES_JSON_IN_OBJ); |  | ||||||
|                             $obj = array(); |  | ||||||
|                         } else { |  | ||||||
|                             $stk = array(SERVICES_JSON_IN_OBJ); |  | ||||||
|                             $obj = new stdClass(); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     array_push($stk, array('what'  => SERVICES_JSON_SLICE, |  | ||||||
|                                            'where' => 0, |  | ||||||
|                                            'delim' => false)); |  | ||||||
| 
 |  | ||||||
|                     $chrs = substr($str, 1, -1); |  | ||||||
|                     $chrs = $this->reduce_string($chrs); |  | ||||||
| 
 |  | ||||||
|                     if ($chrs == '') { |  | ||||||
|                         if (reset($stk) == SERVICES_JSON_IN_ARR) { |  | ||||||
|                             return $arr; |  | ||||||
| 
 |  | ||||||
|                         } else { |  | ||||||
|                             return $obj; |  | ||||||
| 
 |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     //print("\nparsing {$chrs}\n");
 |  | ||||||
| 
 |  | ||||||
|                     $strlen_chrs = strlen($chrs); |  | ||||||
| 
 |  | ||||||
|                     for ($c = 0; $c <= $strlen_chrs; ++$c) { |  | ||||||
| 
 |  | ||||||
|                         $top = end($stk); |  | ||||||
|                         $substr_chrs_c_2 = substr($chrs, $c, 2); |  | ||||||
| 
 |  | ||||||
|                         if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { |  | ||||||
|                             // found a comma that is not inside a string, array, etc.,
 |  | ||||||
|                             // OR we've reached the end of the character list
 |  | ||||||
|                             $slice = substr($chrs, $top['where'], ($c - $top['where'])); |  | ||||||
|                             array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); |  | ||||||
|                             //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 |  | ||||||
| 
 |  | ||||||
|                             if (reset($stk) == SERVICES_JSON_IN_ARR) { |  | ||||||
|                                 // we are in an array, so just push an element onto the stack
 |  | ||||||
|                                 array_push($arr, $this->decode($slice)); |  | ||||||
| 
 |  | ||||||
|                             } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |  | ||||||
|                                 // we are in an object, so figure
 |  | ||||||
|                                 // out the property name and set an
 |  | ||||||
|                                 // element in an associative array,
 |  | ||||||
|                                 // for now
 |  | ||||||
|                                 $parts = array(); |  | ||||||
|                                  |  | ||||||
|                                 if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |  | ||||||
|                                     // "name":value pair
 |  | ||||||
|                                     $key = $this->decode($parts[1]); |  | ||||||
|                                     $val = $this->decode($parts[2]); |  | ||||||
| 
 |  | ||||||
|                                     if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |  | ||||||
|                                         $obj[$key] = $val; |  | ||||||
|                                     } else { |  | ||||||
|                                         $obj->$key = $val; |  | ||||||
|                                     } |  | ||||||
|                                 } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |  | ||||||
|                                     // name:value pair, where name is unquoted
 |  | ||||||
|                                     $key = $parts[1]; |  | ||||||
|                                     $val = $this->decode($parts[2]); |  | ||||||
| 
 |  | ||||||
|                                     if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |  | ||||||
|                                         $obj[$key] = $val; |  | ||||||
|                                     } else { |  | ||||||
|                                         $obj->$key = $val; |  | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
| 
 |  | ||||||
|                             } |  | ||||||
| 
 |  | ||||||
|                         } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { |  | ||||||
|                             // found a quote, and we are not inside a string
 |  | ||||||
|                             array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); |  | ||||||
|                             //print("Found start of string at {$c}\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($chrs{$c} == $top['delim']) && |  | ||||||
|                                  ($top['what'] == SERVICES_JSON_IN_STR) && |  | ||||||
|                                  (($chrs{$c - 1} != '\\') || |  | ||||||
|                                  ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) { |  | ||||||
|                             // found a quote, we're in a string, and it's not escaped
 |  | ||||||
|                             array_pop($stk); |  | ||||||
|                             //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($chrs{$c} == '[') && |  | ||||||
|                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |  | ||||||
|                             // found a left-bracket, and we are in an array, object, or slice
 |  | ||||||
|                             array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); |  | ||||||
|                             //print("Found start of array at {$c}\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { |  | ||||||
|                             // found a right-bracket, and we're in an array
 |  | ||||||
|                             array_pop($stk); |  | ||||||
|                             //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($chrs{$c} == '{') && |  | ||||||
|                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |  | ||||||
|                             // found a left-brace, and we are in an array, object, or slice
 |  | ||||||
|                             array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); |  | ||||||
|                             //print("Found start of object at {$c}\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { |  | ||||||
|                             // found a right-brace, and we're in an object
 |  | ||||||
|                             array_pop($stk); |  | ||||||
|                             //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($substr_chrs_c_2 == '/*') && |  | ||||||
|                                  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |  | ||||||
|                             // found a comment start, and we are in an array, object, or slice
 |  | ||||||
|                             array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); |  | ||||||
|                             $c++; |  | ||||||
|                             //print("Found start of comment at {$c}\n");
 |  | ||||||
| 
 |  | ||||||
|                         } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { |  | ||||||
|                             // found a comment end, and we're in one now
 |  | ||||||
|                             array_pop($stk); |  | ||||||
|                             $c++; |  | ||||||
| 
 |  | ||||||
|                             for ($i = $top['where']; $i <= $c; ++$i) |  | ||||||
|                                 $chrs = substr_replace($chrs, ' ', $i, 1); |  | ||||||
| 
 |  | ||||||
|                             //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 |  | ||||||
| 
 |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     if (reset($stk) == SERVICES_JSON_IN_ARR) { |  | ||||||
|                         return $arr; |  | ||||||
| 
 |  | ||||||
|                     } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |  | ||||||
|                         return $obj; |  | ||||||
| 
 |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                 } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * @todo Ultimately, this should just call PEAR::isError() |  | ||||||
|      */ |  | ||||||
|     function isError($data, $code = null) |  | ||||||
|     { |  | ||||||
|         if (class_exists('pear')) { |  | ||||||
|             return PEAR::isError($data, $code); |  | ||||||
|         } elseif (is_object($data) && (get_class($data) == 'services_json_error' || |  | ||||||
|                                  is_subclass_of($data, 'services_json_error'))) { |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| if (class_exists('PEAR_Error')) { |  | ||||||
| 
 |  | ||||||
|     class Services_JSON_Error extends PEAR_Error |  | ||||||
|     { |  | ||||||
|         function Services_JSON_Error($message = 'unknown error', $code = null, |  | ||||||
|                                      $mode = null, $options = null, $userinfo = null) |  | ||||||
|         { |  | ||||||
|             parent::PEAR_Error($message, $code, $mode, $options, $userinfo); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } else { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * @todo Ultimately, this class shall be descended from PEAR_Error |  | ||||||
|      */ |  | ||||||
|     class Services_JSON_Error |  | ||||||
|     { |  | ||||||
|         function Services_JSON_Error($message = 'unknown error', $code = null, |  | ||||||
|                                      $mode = null, $options = null, $userinfo = null) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|      |  | ||||||
| ?>
 |  | ||||||
| @ -246,7 +246,6 @@ class YShout { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,8 +1,10 @@ | |||||||
| <?php | <?php | ||||||
|  | 
 | ||||||
| error_reporting(E_ALL); | error_reporting(E_ALL); | ||||||
| ob_start(); | ob_start(); | ||||||
| set_error_handler('errorOccurred'); | set_error_handler('errorOccurred'); | ||||||
| include 'include.php'; | include 'include.php'; | ||||||
|  | 
 | ||||||
| if (isset($_POST['reqFor'])) | if (isset($_POST['reqFor'])) | ||||||
| 	switch($_POST['reqFor']) { | 	switch($_POST['reqFor']) { | ||||||
| 		case 'shout': | 		case 'shout': | ||||||
| @ -20,20 +22,17 @@ if (isset($_POST['reqFor'])) | |||||||
| 
 | 
 | ||||||
| 		default: | 		default: | ||||||
| 			exit; | 			exit; | ||||||
| 	} | 	} else { | ||||||
| else |  | ||||||
| 		include 'example.html'; | 		include 'example.html'; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| function errorOccurred($num, $str, $file, $line) { | function errorOccurred($num, $str, $file, $line) { | ||||||
| 	$err = array ( | 	$err = array ( | ||||||
| 		'yError' => "$str. \n File: $file \n Line: $line" | 		'yError' => "$str. \n File: $file \n Line: $line" | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	if (function_exists('jsonEncode')) | 	echo json_encode($err); | ||||||
| 		echo jsonEncode($err); | 
 | ||||||
| 	else |  | ||||||
| 		echo $err['yError']; |  | ||||||
| 	exit; | 	exit; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ?>
 |  | ||||||
| @ -12,8 +12,18 @@ | |||||||
| require_once "lib/akismet.class.php"; | require_once "lib/akismet.class.php"; | ||||||
| 
 | 
 | ||||||
| class CommentPostingEvent extends Event { | class CommentPostingEvent extends Event { | ||||||
| 	var $image_id, $user, $comment; | 	/** @var  int */ | ||||||
|  | 	public $image_id; | ||||||
|  | 	/** @var \User */ | ||||||
|  | 	public $user; | ||||||
|  | 	/** @var string  */ | ||||||
|  | 	public $comment; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param \User $user | ||||||
|  | 	 * @param string $comment | ||||||
|  | 	 */ | ||||||
| 	public function __construct($image_id, $user, $comment) { | 	public function __construct($image_id, $user, $comment) { | ||||||
| 		$this->image_id = $image_id; | 		$this->image_id = $image_id; | ||||||
| 		$this->user = $user; | 		$this->user = $user; | ||||||
| @ -27,8 +37,12 @@ class CommentPostingEvent extends Event { | |||||||
|  * and what should be kept? |  * and what should be kept? | ||||||
|  */ |  */ | ||||||
| class CommentDeletionEvent extends Event { | class CommentDeletionEvent extends Event { | ||||||
| 	var $comment_id; | 	/** @var  int */ | ||||||
|  | 	public $comment_id; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $comment_id | ||||||
|  | 	 */ | ||||||
| 	public function __construct($comment_id) { | 	public function __construct($comment_id) { | ||||||
| 		$this->comment_id = $comment_id; | 		$this->comment_id = $comment_id; | ||||||
| 	} | 	} | ||||||
| @ -54,11 +68,18 @@ class Comment { | |||||||
| 		$this->posted =  $row['posted']; | 		$this->posted =  $row['posted']; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \User $user | ||||||
|  | 	 * @return mixed | ||||||
|  | 	 */ | ||||||
| 	public static function count_comments_by_user($user) { | 	public static function count_comments_by_user($user) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		return $database->get_one("SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id", array("owner_id"=>$user->id)); | 		return $database->get_one("SELECT COUNT(*) AS count FROM comments WHERE owner_id=:owner_id", array("owner_id"=>$user->id)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return null|User | ||||||
|  | 	 */ | ||||||
| 	public function get_owner() { | 	public function get_owner() { | ||||||
| 		if(empty($this->owner)) $this->owner = User::by_id($this->owner_id); | 		if(empty($this->owner)) $this->owner = User::by_id($this->owner_id); | ||||||
| 		return $this->owner; | 		return $this->owner; | ||||||
| @ -265,19 +286,20 @@ class CommentList extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onSearchTermParse(SearchTermParseEvent $event) { | 	public function onSearchTermParse(SearchTermParseEvent $event) { | ||||||
|  | 		global $database; | ||||||
|  | 
 | ||||||
| 		$matches = array(); | 		$matches = array(); | ||||||
|  | 
 | ||||||
| 		if(preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { | 		if(preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) { | ||||||
| 			$cmp = ltrim($matches[1], ":") ?: "="; | 			$cmp = ltrim($matches[1], ":") ?: "="; | ||||||
| 			$comments = $matches[2]; | 			$comments = $matches[2]; | ||||||
| 			$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)")); | 			$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)")); | ||||||
| 		} | 		} | ||||||
| 		else if(preg_match("/^commented_by[=|:](.*)$/i", $event->term, $matches)) { | 		else if(preg_match("/^commented_by[=|:](.*)$/i", $event->term, $matches)) { | ||||||
| 			global $database; |  | ||||||
| 			$user = User::by_name($matches[1]); | 			$user = User::by_name($matches[1]); | ||||||
| 			if(!is_null($user)) { | 			if(!is_null($user)) { | ||||||
| 				$user_id = $user->id; | 				$user_id = $user->id; | ||||||
| 			} | 			} else { | ||||||
| 			else { |  | ||||||
| 				$user_id = -1; | 				$user_id = -1; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| @ -290,11 +312,16 @@ class CommentList extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| // page building {{{
 | // page building {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $current_page | ||||||
|  | 	 */ | ||||||
| 	private function build_page(/*int*/ $current_page) { | 	private function build_page(/*int*/ $current_page) { | ||||||
| 		global $page, $config, $database, $user; | 		global $database, $user; | ||||||
| 
 | 
 | ||||||
| 		if(class_exists("Ratings")) { | 		if(class_exists("Ratings")) { | ||||||
| 			$user_ratings = Ratings::get_user_privs($user); | 			$user_ratings = Ratings::get_user_privs($user); | ||||||
|  | 		} else { | ||||||
|  | 			$user_ratings = ""; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; | 		$where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; | ||||||
| @ -341,8 +368,12 @@ class CommentList extends Extension { | |||||||
| // }}}
 | // }}}
 | ||||||
| 
 | 
 | ||||||
| // get comments {{{
 | // get comments {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $count | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	private function get_recent_comments($count) { | 	private function get_recent_comments($count) { | ||||||
| 		global $config, $database; | 		global $database; | ||||||
| 		$rows = $database->get_all(" | 		$rows = $database->get_all(" | ||||||
| 				SELECT | 				SELECT | ||||||
| 				users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, | 				users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, | ||||||
| @ -361,8 +392,14 @@ class CommentList extends Extension { | |||||||
| 		return $comments; | 		return $comments; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $user_id | ||||||
|  | 	 * @param int $count | ||||||
|  | 	 * @param int $offset | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	private function get_user_comments(/*int*/ $user_id, /*int*/ $count, /*int*/ $offset=0) { | 	private function get_user_comments(/*int*/ $user_id, /*int*/ $count, /*int*/ $offset=0) { | ||||||
| 		global $config, $database; | 		global $database; | ||||||
| 		$rows = $database->get_all(" | 		$rows = $database->get_all(" | ||||||
| 				SELECT | 				SELECT | ||||||
| 				users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, | 				users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class, | ||||||
| @ -382,8 +419,12 @@ class CommentList extends Extension { | |||||||
| 		return $comments; | 		return $comments; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	private function get_comments(/*int*/ $image_id) { | 	private function get_comments(/*int*/ $image_id) { | ||||||
| 		global $config, $database; | 		global $database; | ||||||
| 		$i_image_id = int_escape($image_id); | 		$i_image_id = int_escape($image_id); | ||||||
| 		$rows = $database->get_all(" | 		$rows = $database->get_all(" | ||||||
| 				SELECT | 				SELECT | ||||||
| @ -425,6 +466,9 @@ class CommentList extends Extension { | |||||||
| 		return (count($result) >= $max); | 		return (count($result) >= $max); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function hash_match() { | 	private function hash_match() { | ||||||
| 		return ($_POST['hash'] == $this->get_hash()); | 		return ($_POST['hash'] == $this->get_hash()); | ||||||
| 	} | 	} | ||||||
| @ -440,6 +484,10 @@ class CommentList extends Extension { | |||||||
| 		return md5($_SERVER['REMOTE_ADDR'] . date("%Y%m%d")); | 		return md5($_SERVER['REMOTE_ADDR'] . date("%Y%m%d")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function is_spam_akismet(/*string*/ $text) { | 	private function is_spam_akismet(/*string*/ $text) { | ||||||
| 		global $config, $user; | 		global $config, $user; | ||||||
| 		if(strlen($config->get_string('comment_wordpress_key')) > 0) { | 		if(strlen($config->get_string('comment_wordpress_key')) > 0) { | ||||||
| @ -478,11 +526,22 @@ class CommentList extends Extension { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param int $comment | ||||||
|  | 	 * @return null | ||||||
|  | 	 */ | ||||||
| 	private function is_dupe(/*int*/ $image_id, /*string*/ $comment) { | 	private function is_dupe(/*int*/ $image_id, /*string*/ $comment) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		return ($database->get_row("SELECT * FROM comments WHERE image_id=:image_id AND comment=:comment", array("image_id"=>$image_id, "comment"=>$comment))); | 		return ($database->get_row("SELECT * FROM comments WHERE image_id=:image_id AND comment=:comment", array("image_id"=>$image_id, "comment"=>$comment))); | ||||||
| 	} | 	} | ||||||
| // do some checks
 | // do some checks
 | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $pagenum | ||||||
|  | 	 * @param int $maxpage | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	private function sanity_check_pagenumber(/*int*/ $pagenum, /*int*/ $maxpage){ | 	private function sanity_check_pagenumber(/*int*/ $pagenum, /*int*/ $maxpage){ | ||||||
| 		if (!is_numeric($pagenum)){ | 		if (!is_numeric($pagenum)){ | ||||||
| 			$pagenum=1; | 			$pagenum=1; | ||||||
| @ -496,6 +555,12 @@ class CommentList extends Extension { | |||||||
| 		return $pagenum; | 		return $pagenum; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param User $user | ||||||
|  | 	 * @param string $comment | ||||||
|  | 	 * @throws CommentPostingException | ||||||
|  | 	 */ | ||||||
| 	private function add_comment_wrapper(/*int*/ $image_id, User $user, /*string*/ $comment) { | 	private function add_comment_wrapper(/*int*/ $image_id, User $user, /*string*/ $comment) { | ||||||
| 		global $database, $config; | 		global $database, $config; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,8 +18,12 @@ class CommentListTheme extends Themelet { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Display a page with a list of images, and for each image, | 	 * Display a page with a list of images, and for each image, the image's comments. | ||||||
| 	 * the image's comments | 	 * | ||||||
|  | 	 * @param array $images | ||||||
|  | 	 * @param int $page_number | ||||||
|  | 	 * @param int $total_pages | ||||||
|  | 	 * @param bool $can_post | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_comment_list($images, $page_number, $total_pages, $can_post) { | 	public function display_comment_list($images, $page_number, $total_pages, $can_post) { | ||||||
| 		global $config, $page, $user; | 		global $config, $page, $user; | ||||||
| @ -119,9 +123,9 @@ class CommentListTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Add some comments to the page, probably in a sidebar | 	 * Add some comments to the page, probably in a sidebar. | ||||||
| 	 * | 	 * | ||||||
| 	 * $comments = an array of Comment objects to be shown | 	 * @param \Comment[] $comments An array of Comment objects to be shown | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_recent_comments($comments) { | 	public function display_recent_comments($comments) { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -136,7 +140,11 @@ class CommentListTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Show comments for an image | 	 * Show comments for an image. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param \Comment[] $comments | ||||||
|  | 	 * @param bool $postbox | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_image_comments(Image $image, $comments, $postbox) { | 	public function display_image_comments(Image $image, $comments, $postbox) { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -153,9 +161,12 @@ class CommentListTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Show comments made by a user | 	 * Show comments made by a user. | ||||||
|  | 	 * | ||||||
|  | 	 * @param \Comment[] $comments | ||||||
|  | 	 * @param \User $user | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_recent_user_comments($comments, $user) { | 	public function display_recent_user_comments($comments, User $user) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 		$html = ""; | 		$html = ""; | ||||||
| 		foreach($comments as $comment) { | 		foreach($comments as $comment) { | ||||||
| @ -170,7 +181,13 @@ class CommentListTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Comments", $html, "left", 70, "comment-list-user")); | 		$page->add_block(new Block("Comments", $html, "left", 70, "comment-list-user")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function display_all_user_comments($comments, $page_number, $total_pages, $user) { | 	/** | ||||||
|  | 	 * @param \Comment[] $comments | ||||||
|  | 	 * @param int $page_number | ||||||
|  | 	 * @param int $total_pages | ||||||
|  | 	 * @param \User $user | ||||||
|  | 	 */ | ||||||
|  | 	public function display_all_user_comments($comments, $page_number, $total_pages, User $user) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 		 | 		 | ||||||
| 		assert(is_numeric($page_number)); | 		assert(is_numeric($page_number)); | ||||||
| @ -203,7 +220,12 @@ class CommentListTheme extends Themelet { | |||||||
| 		$this->display_paginator($page, "comment/beta-search/{$user->name}", null, $page_number, $total_pages); | 		$this->display_paginator($page, "comment/beta-search/{$user->name}", null, $page_number, $total_pages); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	protected function comment_to_html($comment, $trim=false) { | 	/** | ||||||
|  | 	 * @param \Comment $comment | ||||||
|  | 	 * @param bool $trim | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
|  | 	protected function comment_to_html(Comment $comment, $trim=false) { | ||||||
| 		global $config, $user; | 		global $config, $user; | ||||||
| 
 | 
 | ||||||
| 		$tfe = new TextFormattingEvent($comment->comment); | 		$tfe = new TextFormattingEvent($comment->comment); | ||||||
| @ -276,6 +298,10 @@ class CommentListTheme extends Themelet { | |||||||
| 		return $html; | 		return $html; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function build_postbox(/*int*/ $image_id) { | 	protected function build_postbox(/*int*/ $image_id) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -30,6 +30,12 @@ class CronUploader extends Extension { | |||||||
| 	 */ | 	 */ | ||||||
| 	private $root_dir = ""; | 	private $root_dir = ""; | ||||||
| 	 | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * Key used to identify uploader | ||||||
|  | 	 * @var string | ||||||
|  | 	 */ | ||||||
|  | 	private $upload_key = ""; | ||||||
|  | 	 | ||||||
| 	/** | 	/** | ||||||
| 	 * Checks if the cron upload page has been accessed | 	 * Checks if the cron upload page has been accessed | ||||||
| 	 * and initializes the upload. | 	 * and initializes the upload. | ||||||
| @ -39,10 +45,10 @@ class CronUploader extends Extension { | |||||||
| 		global $config, $user; | 		global $config, $user; | ||||||
| 		 | 		 | ||||||
| 		if ($event->page_matches ( "cron_upload" )) { | 		if ($event->page_matches ( "cron_upload" )) { | ||||||
| 			$key = $config->get_string ( "cron_uploader_key", "" ); | 			$this->upload_key = $config->get_string ( "cron_uploader_key", "" ); | ||||||
| 			 | 			 | ||||||
| 			// If the key is in the url, upload
 | 			// If the key is in the url, upload
 | ||||||
| 			if ($key != "" && $event->get_arg ( 0 ) == $key) { | 			if ($this->upload_key != "" && $event->get_arg ( 0 ) == $this->upload_key) { | ||||||
| 				// log in as admin
 | 				// log in as admin
 | ||||||
| 				$this->process_upload(); // Start upload
 | 				$this->process_upload(); // Start upload
 | ||||||
| 			}  | 			}  | ||||||
| @ -67,8 +73,8 @@ class CronUploader extends Extension { | |||||||
| 		$uploaded_dirinfo = $this->scan_dir($uploaded_dir); | 		$uploaded_dirinfo = $this->scan_dir($uploaded_dir); | ||||||
| 		$failed_dirinfo = $this->scan_dir($failed_dir); | 		$failed_dirinfo = $this->scan_dir($failed_dir); | ||||||
| 		 | 		 | ||||||
| 		$cron_url = make_http(make_link("/cron_upload/" . $config->get_string('cron_uploader_key', 'invalid key' ))); | 		$cron_url = make_http(make_link("/cron_upload/" . $this->upload_key)); | ||||||
| 		$cron_cmd = "curl -f $cron_url"; | 		$cron_cmd = "curl --silent $cron_url"; | ||||||
| 		$log_path = $this->root_dir . "/uploads.log"; | 		$log_path = $this->root_dir . "/uploads.log"; | ||||||
| 		 | 		 | ||||||
| 		$info_html = "<b>Information</b>
 | 		$info_html = "<b>Information</b>
 | ||||||
| @ -135,19 +141,21 @@ class CronUploader extends Extension { | |||||||
| 	public function onInitExt(InitExtEvent $event) { | 	public function onInitExt(InitExtEvent $event) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		// Set default values
 | 		// Set default values
 | ||||||
| 		$key = $this->generate_key (); | 		if ($config->get_string("cron_uploader_key", "")) { | ||||||
|  | 			$this->upload_key = $this->generate_key (); | ||||||
| 	 | 	 | ||||||
| 			$config->set_default_int ( 'cron_uploader_count', 1 ); | 			$config->set_default_int ( 'cron_uploader_count', 1 ); | ||||||
| 		$config->set_default_string ( 'cron_uploader_key', $key ); | 			$config->set_default_string ( 'cron_uploader_key', $this->upload_key ); | ||||||
| 			$this->set_dir(); | 			$this->set_dir(); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 	 | 	 | ||||||
| 	public function onSetupBuilding(SetupBuildingEvent $event) { | 	public function onSetupBuilding(SetupBuildingEvent $event) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$this->set_dir(); | 		$this->set_dir(); | ||||||
| 		 | 		 | ||||||
| 		$cron_url = make_http(make_link("/cron_upload/" . $config->get_string('cron_uploader_key', 'invalid key' ))); | 		$cron_url = make_http(make_link("/cron_upload/" . $this->upload_key)); | ||||||
| 		$cron_cmd = "wget $cron_url"; | 		$cron_cmd = "curl --silent $cron_url"; | ||||||
| 		$documentation_link = make_http(make_link("cron_upload")); | 		$documentation_link = make_http(make_link("cron_upload")); | ||||||
| 		 | 		 | ||||||
| 		$sb = new SetupBlock ( "Cron Uploader" ); | 		$sb = new SetupBlock ( "Cron Uploader" ); | ||||||
| @ -194,11 +202,11 @@ class CronUploader extends Extension { | |||||||
| 			 | 			 | ||||||
| 		// Make the directory if it doesn't exist yet
 | 		// Make the directory if it doesn't exist yet
 | ||||||
| 		if (!is_dir($dir . "/queue/"))  | 		if (!is_dir($dir . "/queue/"))  | ||||||
| 			mkdir ( $dir . "/queue/", 0755, true ); | 			mkdir ( $dir . "/queue/", 0775, true ); | ||||||
| 		if (!is_dir($dir . "/uploaded/"))  | 		if (!is_dir($dir . "/uploaded/"))  | ||||||
| 			mkdir ( $dir . "/uploaded/", 0755, true ); | 			mkdir ( $dir . "/uploaded/", 0775, true ); | ||||||
| 		if (!is_dir($dir . "/failed_to_upload/"))  | 		if (!is_dir($dir . "/failed_to_upload/"))  | ||||||
| 			mkdir ( $dir . "/failed_to_upload/", 0755, true ); | 			mkdir ( $dir . "/failed_to_upload/", 0775, true ); | ||||||
| 		 | 		 | ||||||
| 		$this->root_dir = $dir; | 		$this->root_dir = $dir; | ||||||
| 		return $dir; | 		return $dir; | ||||||
| @ -242,6 +250,7 @@ class CronUploader extends Extension { | |||||||
| 		// Throw exception if there's nothing in the queue
 | 		// Throw exception if there's nothing in the queue
 | ||||||
| 		if (count($this->image_queue) == 0) { | 		if (count($this->image_queue) == 0) { | ||||||
| 			$this->add_upload_info("Your queue is empty so nothing could be uploaded."); | 			$this->add_upload_info("Your queue is empty so nothing could be uploaded."); | ||||||
|  | 			$this->handle_log(); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| @ -289,10 +298,9 @@ class CronUploader extends Extension { | |||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		// move file to correct dir
 | 		// move file to correct dir
 | ||||||
| 		$newPath = $newDir . $filename; | 		rename($path, $newDir.$filename); | ||||||
| 		rename($path, $newPath); |  | ||||||
| 		 | 		 | ||||||
| 		$this->add_upload_info($info . "Image \"$filename\" moved from queue to \"$newPath\".");
 | 		$this->add_upload_info($info . "Image \"$filename\" moved from queue to \"$newDir\".");
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | |||||||
| @ -420,8 +420,7 @@ class DanbooruApi extends Extension { | |||||||
| 			// Code borrowed from /ext/user
 | 			// Code borrowed from /ext/user
 | ||||||
| 			$name = $_REQUEST['login']; | 			$name = $_REQUEST['login']; | ||||||
| 			$pass = $_REQUEST['password']; | 			$pass = $_REQUEST['password']; | ||||||
| 			$hash = md5( strtolower($name) . $pass ); | 			$duser = User::by_name_and_pass($name, $pass); | ||||||
| 			$duser = User::by_name_and_hash($name, $hash); |  | ||||||
| 			if(!is_null($duser)) { | 			if(!is_null($duser)) { | ||||||
| 				$user = $duser; | 				$user = $duser; | ||||||
| 			} else | 			} else | ||||||
|  | |||||||
| @ -13,18 +13,32 @@ | |||||||
|  *  add more emoticons by uploading images into that folder. |  *  add more emoticons by uploading images into that folder. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Class Emoticons | ||||||
|  |  */ | ||||||
| class Emoticons extends FormatterExtension { | class Emoticons extends FormatterExtension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function format(/*string*/ $text) { | 	public function format(/*string*/ $text) { | ||||||
| 		$data_href = get_base_href(); | 		$data_href = get_base_href(); | ||||||
| 		$text = preg_replace("/:([a-z]*?):/s", "<img src='$data_href/ext/emoticons/default/\\1.gif'>", $text); | 		$text = preg_replace("/:([a-z]*?):/s", "<img src='$data_href/ext/emoticons/default/\\1.gif'>", $text); | ||||||
| 		return $text; | 		return $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function strip(/*string*/ $text) { | 	public function strip(/*string*/ $text) { | ||||||
| 		return $text; | 		return $text; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Class EmoticonList | ||||||
|  |  */ | ||||||
| class EmoticonList extends Extension { | class EmoticonList extends Extension { | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		if($event->page_matches("emote/list")) { | 		if($event->page_matches("emote/list")) { | ||||||
|  | |||||||
| @ -1,5 +1,8 @@ | |||||||
| <?php | <?php | ||||||
| class EmoticonListTheme extends Themelet { | class EmoticonListTheme extends Themelet { | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $list | ||||||
|  | 	 */ | ||||||
| 	public function display_emotes(/*array*/ $list) { | 	public function display_emotes(/*array*/ $list) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 		$data_href = get_base_href(); | 		$data_href = get_base_href(); | ||||||
|  | |||||||
| @ -81,6 +81,10 @@ class ExtensionInfo { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $fname | ||||||
|  | 	 * @return bool|null | ||||||
|  | 	 */ | ||||||
| 	private function is_enabled(/*string*/ $fname) { | 	private function is_enabled(/*string*/ $fname) { | ||||||
| 		$core = explode(",", CORE_EXTS); | 		$core = explode(",", CORE_EXTS); | ||||||
| 		$extra = explode(",", EXTRA_EXTS); | 		$extra = explode(",", EXTRA_EXTS); | ||||||
| @ -150,7 +154,10 @@ class ExtManager extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
|  | 	 * @param bool $all | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	private function get_extensions(/*bool*/ $all) { | 	private function get_extensions(/*bool*/ $all) { | ||||||
| 		$extensions = array(); | 		$extensions = array(); | ||||||
| 		if($all) { | 		if($all) { | ||||||
|  | |||||||
| @ -14,8 +14,18 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class FavoriteSetEvent extends Event { | class FavoriteSetEvent extends Event { | ||||||
| 	var $image_id, $user, $do_set; | 	/** @var int */ | ||||||
|  | 	public $image_id; | ||||||
|  | 	/** @var \User */ | ||||||
|  | 	public $user; | ||||||
|  | 	/** @var bool */ | ||||||
|  | 	public $do_set; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param User $user | ||||||
|  | 	 * @param bool $do_set | ||||||
|  | 	 */ | ||||||
| 	public function __construct(/*int*/ $image_id, User $user, /*boolean*/ $do_set) { | 	public function __construct(/*int*/ $image_id, User $user, /*boolean*/ $do_set) { | ||||||
| 		assert(is_numeric($image_id)); | 		assert(is_numeric($image_id)); | ||||||
| 		assert(is_bool($do_set)); | 		assert(is_bool($do_set)); | ||||||
| @ -172,6 +182,11 @@ class Favorites extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param int $user_id | ||||||
|  | 	 * @param bool $do_set | ||||||
|  | 	 */ | ||||||
| 	private function add_vote(/*int*/ $image_id, /*int*/ $user_id, /*bool*/ $do_set) { | 	private function add_vote(/*int*/ $image_id, /*int*/ $user_id, /*bool*/ $do_set) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		if ($do_set) { | 		if ($do_set) { | ||||||
| @ -188,6 +203,10 @@ class Favorites extends Extension { | |||||||
| 			array("image_id"=>$image_id, "user_id"=>$user_id)); | 			array("image_id"=>$image_id, "user_id"=>$user_id)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	private function list_persons_who_have_favorited(Image $image) { | 	private function list_persons_who_have_favorited(Image $image) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -60,13 +60,13 @@ class Featured extends Extension { | |||||||
| 		global $config, $database, $page, $user; | 		global $config, $database, $page, $user; | ||||||
| 		$fid = $config->get_int("featured_id"); | 		$fid = $config->get_int("featured_id"); | ||||||
| 		if($fid > 0) { | 		if($fid > 0) { | ||||||
| 			$image = $database->cache->get("featured_image_object-$fid"); | 			$image = $database->cache->get("featured_image_object:$fid"); | ||||||
| 			if($image === false) { | 			if($image === false) { | ||||||
| 				$image = Image::by_id($fid); | 				$image = Image::by_id($fid); | ||||||
| 				if($image) { // make sure the object is fully populated before saving
 | 				if($image) { // make sure the object is fully populated before saving
 | ||||||
| 					$image->get_tag_array(); | 					$image->get_tag_array(); | ||||||
| 				} | 				} | ||||||
| 				$database->cache->set("featured_image_object-$fid", $image, 600); | 				$database->cache->set("featured_image_object:$fid", $image, 600); | ||||||
| 			} | 			} | ||||||
| 			if(!is_null($image)) { | 			if(!is_null($image)) { | ||||||
| 				if(class_exists("Ratings")) { | 				if(class_exists("Ratings")) { | ||||||
|  | |||||||
| @ -1,26 +1,37 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class FeaturedTheme extends Themelet { | class FeaturedTheme extends Themelet { | ||||||
| 	/* | 	/** | ||||||
| 	 * Show $text on the $page | 	 * Show $text on the $page. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param Image $image | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_featured(Page $page, Image $image) { | 	public function display_featured(Page $page, Image $image) { | ||||||
| 		$page->add_block(new Block("Featured Image", $this->build_featured_html($image), "left", 3)); | 		$page->add_block(new Block("Featured Image", $this->build_featured_html($image), "left", 3)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function get_buttons_html(/*int*/ $image_id) { | 	public function get_buttons_html(/*int*/ $image_id) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 		return " | 		return " | ||||||
| 			".make_form(make_link("featured_image/set"))." | 			".make_form(make_link("featured_image/set"))." | ||||||
| 			".$user->get_auth_html()." | 			".$user->get_auth_html()." | ||||||
| 			<input type='hidden' name='image_id' value='$image_id'> | 			<input type='hidden' name='image_id' value='{$image_id}'> | ||||||
| 			<input type='submit' value='Feature This'> | 			<input type='submit' value='Feature This'> | ||||||
| 			</form> | 			</form> | ||||||
| 		";
 | 		";
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param null|string $query | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function build_featured_html(Image $image, $query=null) { | 	public function build_featured_html(Image $image, $query=null) { | ||||||
| 		global $config; |  | ||||||
| 		$i_id = int_escape($image->id); | 		$i_id = int_escape($image->id); | ||||||
| 		$h_view_link = make_link("post/view/$i_id", $query); | 		$h_view_link = make_link("post/view/$i_id", $query); | ||||||
| 		$h_thumb_link = $image->get_thumb_link(); | 		$h_thumb_link = $image->get_thumb_link(); | ||||||
| @ -29,7 +40,7 @@ class FeaturedTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 		return " | 		return " | ||||||
| 			<a href='$h_view_link'> | 			<a href='$h_view_link'> | ||||||
| 				<img id='thumb_$i_id' title='$h_tip' alt='$h_tip' class='highlighted' style='height: {$tsize[1]}px; width: {$tsize[0]}px;' src='$h_thumb_link'> | 				<img id='thumb_{$i_id}' title='{$h_tip}' alt='{$h_tip}' class='highlighted' style='height: {$tsize[1]}px; width: {$tsize[0]}px;' src='{$h_thumb_link}'> | ||||||
| 			</a> | 			</a> | ||||||
| 		";
 | 		";
 | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -39,7 +39,10 @@ class ArchiveFileHandler extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
|  | 	 * @param $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function supported_ext($ext) { | 	private function supported_ext($ext) { | ||||||
| 		$exts = array("zip"); | 		$exts = array("zip"); | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
|  | |||||||
| @ -7,15 +7,29 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class FlashFileHandler extends DataHandlerExtension { | class FlashFileHandler extends DataHandlerExtension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function create_thumb($hash) { | 	protected function create_thumb($hash) { | ||||||
| 		copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash)); | 		copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash)); | ||||||
|  | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function supported_ext($ext) { | 	protected function supported_ext($ext) { | ||||||
| 		$exts = array("swf"); | 		$exts = array("swf"); | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @param array $metadata | ||||||
|  | 	 * @return Image|null | ||||||
|  | 	 */ | ||||||
| 	protected function create_image_from_data(/*string*/ $filename, /*array*/ $metadata) { | 	protected function create_image_from_data(/*string*/ $filename, /*array*/ $metadata) { | ||||||
| 		$image = new Image(); | 		$image = new Image(); | ||||||
| 
 | 
 | ||||||
| @ -35,6 +49,10 @@ class FlashFileHandler extends DataHandlerExtension { | |||||||
| 		return $image; | 		return $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $file | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function check_contents(/*string*/ $file) { | 	protected function check_contents(/*string*/ $file) { | ||||||
| 		if (!file_exists($file)) return false; | 		if (!file_exists($file)) return false; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -49,12 +49,20 @@ class IcoFileHandler extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
|  | 	 * @param $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function supported_ext($ext) { | 	private function supported_ext($ext) { | ||||||
| 		$exts = array("ico", "ani", "cur"); | 		$exts = array("ico", "ani", "cur"); | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $filename | ||||||
|  | 	 * @param $metadata | ||||||
|  | 	 * @return Image | ||||||
|  | 	 */ | ||||||
| 	private function create_image_from_data($filename, $metadata) { | 	private function create_image_from_data($filename, $metadata) { | ||||||
| 		$image = new Image(); | 		$image = new Image(); | ||||||
| 
 | 
 | ||||||
| @ -77,6 +85,10 @@ class IcoFileHandler extends Extension { | |||||||
| 		return $image; | 		return $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $file | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function check_contents($file) { | 	private function check_contents($file) { | ||||||
| 		if(!file_exists($file)) return false; | 		if(!file_exists($file)) return false; | ||||||
| 		$fp = fopen($file, "r"); | 		$fp = fopen($file, "r"); | ||||||
| @ -85,6 +97,10 @@ class IcoFileHandler extends Extension { | |||||||
| 		return ($header['null'] == 0 && ($header['type'] == 0 || $header['type'] == 1)); | 		return ($header['null'] == 0 && ($header['type'] == 0 || $header['type'] == 1)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function create_thumb($hash) { | 	private function create_thumb($hash) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,15 +6,29 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class MP3FileHandler extends DataHandlerExtension { | class MP3FileHandler extends DataHandlerExtension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function create_thumb($hash) { | 	protected function create_thumb($hash) { | ||||||
| 		copy("ext/handle_mp3/thumb.jpg", warehouse_path("thumbs", $hash)); | 		copy("ext/handle_mp3/thumb.jpg", warehouse_path("thumbs", $hash)); | ||||||
|  | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function supported_ext($ext) { | 	protected function supported_ext($ext) { | ||||||
| 		$exts = array("mp3"); | 		$exts = array("mp3"); | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @param array $metadata | ||||||
|  | 	 * @return Image|null | ||||||
|  | 	 */ | ||||||
| 	protected function create_image_from_data($filename, $metadata) { | 	protected function create_image_from_data($filename, $metadata) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
| @ -47,6 +61,10 @@ class MP3FileHandler extends DataHandlerExtension { | |||||||
| 		return $image; | 		return $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $file | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function check_contents($file) { | 	protected function check_contents($file) { | ||||||
| 		if (file_exists($file)) { | 		if (file_exists($file)) { | ||||||
| 			require_once('lib/getid3/getid3/getid3.php'); | 			require_once('lib/getid3/getid3/getid3.php'); | ||||||
|  | |||||||
| @ -7,12 +7,21 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class PixelFileHandler extends DataHandlerExtension { | class PixelFileHandler extends DataHandlerExtension { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function supported_ext($ext) { | 	protected function supported_ext($ext) { | ||||||
| 		$exts = array("jpg", "jpeg", "gif", "png"); | 		$exts = array("jpg", "jpeg", "gif", "png"); | ||||||
| 		$ext = (($pos = strpos($ext,'?')) !== false) ? substr($ext,0,$pos) : $ext; | 		$ext = (($pos = strpos($ext,'?')) !== false) ? substr($ext,0,$pos) : $ext; | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @param array $metadata | ||||||
|  | 	 * @return Image|null | ||||||
|  | 	 */ | ||||||
| 	protected function create_image_from_data(/*string*/ $filename, /*array*/ $metadata) { | 	protected function create_image_from_data(/*string*/ $filename, /*array*/ $metadata) { | ||||||
| 		$image = new Image(); | 		$image = new Image(); | ||||||
| 
 | 
 | ||||||
| @ -32,6 +41,10 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 		return $image; | 		return $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $file | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function check_contents(/*string*/ $file) { | 	protected function check_contents(/*string*/ $file) { | ||||||
| 		$valid = Array(IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_JPEG); | 		$valid = Array(IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_JPEG); | ||||||
| 		if(!file_exists($file)) return false; | 		if(!file_exists($file)) return false; | ||||||
| @ -41,6 +54,10 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function create_thumb(/*string*/ $hash) { | 	protected function create_thumb(/*string*/ $hash) { | ||||||
| 		$outname = warehouse_path("thumbs", $hash); | 		$outname = warehouse_path("thumbs", $hash); | ||||||
| 		if(file_exists($outname)) { | 		if(file_exists($outname)) { | ||||||
| @ -49,6 +66,10 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 		return $this->create_thumb_force($hash); | 		return $this->create_thumb_force($hash); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function create_thumb_force(/*string*/ $hash) { | 	protected function create_thumb_force(/*string*/ $hash) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
| @ -70,6 +91,9 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 		return $ok; | 		return $ok; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param ImageAdminBlockBuildingEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { | 	public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { | ||||||
| 		$event->add_part(" | 		$event->add_part(" | ||||||
| 			<form> | 			<form> | ||||||
| @ -83,14 +107,22 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 		", 20);
 | 		", 20);
 | ||||||
| 
 | 
 | ||||||
| 		$u_ilink = $event->image->get_image_link(); | 		$u_ilink = $event->image->get_image_link(); | ||||||
|  | 		$nu_enabled = (strpos($u_ilink, '?') !== false ? "<input type='hidden' name='q' value='image/{$event->image->id}.{$event->image->ext}' />" : ""); | ||||||
| 		$event->add_part(" | 		$event->add_part(" | ||||||
| 			<form action='{$u_ilink}'> | 			<form action='{$u_ilink}'> | ||||||
|  | 				$nu_enabled | ||||||
| 				<input type='submit' value='Image Only'> | 				<input type='submit' value='Image Only'> | ||||||
| 			</form> | 			</form> | ||||||
| 		", 21);
 | 		", 21);
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| // IM thumber {{{
 | // IM thumber {{{
 | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $inname | ||||||
|  | 	 * @param string $outname | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function make_thumb_convert(/*string*/ $inname, /*string*/ $outname) { | 	private function make_thumb_convert(/*string*/ $inname, /*string*/ $outname) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
| @ -124,6 +156,11 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 	} | 	} | ||||||
| // }}}
 | // }}}
 | ||||||
| // epeg thumber {{{
 | // epeg thumber {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $inname | ||||||
|  | 	 * @param string $outname | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function make_thumb_epeg(/*string*/ $inname, /*string*/ $outname) { | 	private function make_thumb_epeg(/*string*/ $inname, /*string*/ $outname) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$w = $config->get_int("thumb_width"); | 		$w = $config->get_int("thumb_width"); | ||||||
| @ -132,6 +169,11 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 	} | 	} | ||||||
| 	// }}}
 | 	// }}}
 | ||||||
| // GD thumber {{{
 | // GD thumber {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $inname | ||||||
|  | 	 * @param string $outname | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function make_thumb_gd(/*string*/ $inname, /*string*/ $outname) { | 	private function make_thumb_gd(/*string*/ $inname, /*string*/ $outname) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$thumb = $this->get_thumb($inname); | 		$thumb = $this->get_thumb($inname); | ||||||
| @ -140,6 +182,10 @@ class PixelFileHandler extends DataHandlerExtension { | |||||||
| 		return $ok; | 		return $ok; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $tmpname | ||||||
|  | 	 * @return resource | ||||||
|  | 	 */ | ||||||
| 	private function get_thumb(/*string*/ $tmpname) { | 	private function get_thumb(/*string*/ $tmpname) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -51,11 +51,20 @@ class SVGFileHandler extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function supported_ext($ext) { | 	private function supported_ext($ext) { | ||||||
| 		$exts = array("svg"); | 		$exts = array("svg"); | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $filename | ||||||
|  | 	 * @param $metadata | ||||||
|  | 	 * @return Image | ||||||
|  | 	 */ | ||||||
| 	private function create_image_from_data($filename, $metadata) { | 	private function create_image_from_data($filename, $metadata) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
| @ -75,21 +84,30 @@ class SVGFileHandler extends Extension { | |||||||
| 		return $image; | 		return $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $file | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function check_contents($file) { | 	private function check_contents($file) { | ||||||
| 		if(!file_exists($file)) return false; | 		if(!file_exists($file)) return false; | ||||||
| 
 | 
 | ||||||
| 		$msp = new MiniSVGParser($file); | 		$msp = new MiniSVGParser($file); | ||||||
| 		return $msp->valid; | 		return bool_escape($msp->valid); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class MiniSVGParser { | class MiniSVGParser { | ||||||
| 	var $valid=false, $width=0, $height=0; | 	/** @var bool */ | ||||||
|  | 	public $valid=false; | ||||||
|  | 	/** @var int */ | ||||||
|  | 	public $width=0; | ||||||
|  | 	/** @var int */ | ||||||
|  | 	public $height=0; | ||||||
| 
 | 
 | ||||||
| 	function __construct($file) { | 	function __construct($file) { | ||||||
| 		$xml_parser = xml_parser_create(); | 		$xml_parser = xml_parser_create(); | ||||||
| 		xml_set_element_handler($xml_parser, array($this, "startElement"), array($this, "endElement")); | 		xml_set_element_handler($xml_parser, array($this, "startElement"), array($this, "endElement")); | ||||||
| 		$this->valid = xml_parse($xml_parser, file_get_contents($file), true); | 		$this->valid = bool_escape(xml_parse($xml_parser, file_get_contents($file), true)); | ||||||
| 		xml_parser_free($xml_parser); | 		xml_parser_free($xml_parser); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| /* | /* | ||||||
|  * Name: Handle Video |  * Name: Handle Video | ||||||
|  * Author: velocity37 <velocity37@gmail.com> |  * Author: velocity37 <velocity37@gmail.com> | ||||||
|  |  * Modified By: Shish <webmaster@shishnet.org>, jgen <jeffgenovy@gmail.com> | ||||||
|  * License: GPLv2 |  * License: GPLv2 | ||||||
|  * Description: Handle FLV, MP4, OGV and WEBM video files. |  * Description: Handle FLV, MP4, OGV and WEBM video files. | ||||||
|  * Documentation: |  * Documentation: | ||||||
| @ -17,17 +18,88 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class VideoFileHandler extends DataHandlerExtension { | class VideoFileHandler extends DataHandlerExtension { | ||||||
| 	protected function create_thumb($hash) { | 	public function onInitExt(InitExtEvent $event) { | ||||||
| 		copy("ext/handle_video/thumb.jpg", warehouse_path("thumbs", $hash)); | 		global $config; | ||||||
|  | 		$config->set_default_string('video_thumb_engine', 'static'); | ||||||
|  | 		$config->set_default_string('thumb_ffmpeg_path', ''); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public function onSetupBuilding(SetupBuildingEvent $event) { | ||||||
|  | 		global $config; | ||||||
|  | 
 | ||||||
|  | 		$thumbers = array(); | ||||||
|  | 		$thumbers['None'] = "static"; | ||||||
|  | 		$thumbers['ffmpeg'] = "ffmpeg"; | ||||||
|  | 
 | ||||||
|  | 		$sb = new SetupBlock("Video Thumbnail Options"); | ||||||
|  | 
 | ||||||
|  | 		$sb->add_choice_option("video_thumb_engine", $thumbers, "Engine: "); | ||||||
|  | 
 | ||||||
|  | 		//if($config->get_string("video_thumb_engine") == "ffmpeg") {
 | ||||||
|  | 			$sb->add_label("<br>Path to ffmpeg: "); | ||||||
|  | 			$sb->add_text_option("thumb_ffmpeg_path"); | ||||||
|  | 		//}
 | ||||||
|  | 		$event->panel->add_block($sb); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $hash | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
|  | 	protected function create_thumb($hash) { | ||||||
|  | 		global $config; | ||||||
|  | 
 | ||||||
|  | 		// this is never used...
 | ||||||
|  | 		//$q = $config->get_int("thumb_quality");
 | ||||||
|  | 
 | ||||||
|  | 		$ok = false; | ||||||
|  | 
 | ||||||
|  | 		switch($config->get_string("video_thumb_engine")) | ||||||
|  | 		{ | ||||||
|  | 			default: | ||||||
|  | 			case 'static': | ||||||
|  | 				$outname = warehouse_path("thumbs", $hash); | ||||||
|  | 				copy("ext/handle_video/thumb.jpg", $outname); | ||||||
|  | 				$ok = true; | ||||||
|  | 				break; | ||||||
|  | 			case 'ffmpeg': | ||||||
|  | 				$ffmpeg = escapeshellarg($config->get_string("thumb_ffmpeg_path")); | ||||||
|  | 
 | ||||||
|  | 				$w = (int)$config->get_int("thumb_width"); | ||||||
|  | 				$h = (int)$config->get_int("thumb_height"); | ||||||
|  | 				$inname  = escapeshellarg(warehouse_path("images", $hash)); | ||||||
|  | 				$outname = escapeshellarg(warehouse_path("thumbs", $hash)); | ||||||
|  | 
 | ||||||
|  | 				$cmd = escapeshellcmd("{$ffmpeg} -i {$inname} -vf scale='if(gt(a,{$w}/{$h}),{$w},-1)':'if(gt(a,{$w}/{$h}),-1,{$h})' -ss 00:00:00.0 -f image2 -vframes 1 {$outname}"); | ||||||
|  | 
 | ||||||
|  | 				exec($cmd, $output, $ret); | ||||||
|  | 
 | ||||||
|  | 				// TODO: We should really check the result of the exec to see if it really succeeded.
 | ||||||
|  | 				$ok = true; | ||||||
|  | 
 | ||||||
|  | 				log_debug('handle_video', "Generating thumbnail with command `$cmd`, returns $ret"); | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return $ok; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $ext | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function supported_ext($ext) { | 	protected function supported_ext($ext) { | ||||||
| 		$exts = array("flv", "mp4", "m4v", "ogv", "webm"); | 		$exts = array("flv", "mp4", "m4v", "ogv", "webm"); | ||||||
| 		return in_array(strtolower($ext), $exts); | 		return in_array(strtolower($ext), $exts); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @param array $metadata | ||||||
|  | 	 * @return Image|null | ||||||
|  | 	 */ | ||||||
| 	protected function create_image_from_data($filename, $metadata) { | 	protected function create_image_from_data($filename, $metadata) { | ||||||
| 		global $config; | 		//global $config;
 | ||||||
| 
 | 
 | ||||||
| 		$image = new Image(); | 		$image = new Image(); | ||||||
| 
 | 
 | ||||||
| @ -67,12 +139,21 @@ class VideoFileHandler extends DataHandlerExtension { | |||||||
| 		return $image; | 		return $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $file | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	protected function check_contents($file) { | 	protected function check_contents($file) { | ||||||
| 		if (file_exists($file)) { | 		if (file_exists($file)) { | ||||||
| 			require_once('lib/getid3/getid3/getid3.php'); | 			require_once('lib/getid3/getid3/getid3.php'); | ||||||
| 			$getID3 = new getID3; | 			$getID3 = new getID3; | ||||||
| 			$ThisFileInfo = $getID3->analyze($file); | 			$ThisFileInfo = $getID3->analyze($file); | ||||||
| 			if (isset($ThisFileInfo['mime_type']) && ($ThisFileInfo['mime_type'] == "video/webm" || $ThisFileInfo['mime_type'] == "video/quicktime" || $ThisFileInfo['mime_type'] == "application/ogg" || $ThisFileInfo['mime_type'] == 'video/x-flv')) { | 			if (isset($ThisFileInfo['mime_type']) && ( | ||||||
|  | 					$ThisFileInfo['mime_type'] == "video/webm"      || | ||||||
|  | 					$ThisFileInfo['mime_type'] == "video/quicktime" || | ||||||
|  | 					$ThisFileInfo['mime_type'] == "application/ogg" || | ||||||
|  | 					$ThisFileInfo['mime_type'] == 'video/x-flv') | ||||||
|  | 			) { | ||||||
| 				return TRUE; | 				return TRUE; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -7,27 +7,38 @@ class VideoFileHandlerTheme extends Themelet { | |||||||
| 		$ext = strtolower($image->get_ext()); | 		$ext = strtolower($image->get_ext()); | ||||||
| 		 | 		 | ||||||
| 		if ($ext == "mp4") { | 		if ($ext == "mp4") { | ||||||
| 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br><script language='JavaScript' type='text/javascript'>
 | 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br/>
 | ||||||
|  | 			<script language='JavaScript' type='text/javascript'> | ||||||
| if( navigator.userAgent.match(/Firefox/i) || | if( navigator.userAgent.match(/Firefox/i) || | ||||||
| 	navigator.userAgent.match(/Opera/i) || | 	navigator.userAgent.match(/Opera/i) || | ||||||
| 	(navigator.userAgent.match(/MSIE/i) && parseFloat(navigator.appVersion.split('MSIE')[1]) < 9)){ | 	(navigator.userAgent.match(/MSIE/i) && parseFloat(navigator.appVersion.split('MSIE')[1]) < 9)){ | ||||||
| 		document.write(\"<object data='$data_href/lib/Jaris/bin/JarisFLVPlayer.swf' id='VideoPlayer' type='application/x-shockwave-flash' height='" . strval($image->height + 1). "px' width='" . strval($image->width) . "px'><param value='#000000' name='bgcolor'><param name='allowFullScreen' value='true'><param value='high' name='quality'><param value='opaque' name='wmode'><param value='source=$ilink&type=video&streamtype=file&controltype=0' name='flashvars'></object>\");
 | 		document.write(\"<object data='{$data_href}/lib/Jaris/bin/JarisFLVPlayer.swf' id='VideoPlayer' type='application/x-shockwave-flash' height='" . strval($image->height + 1). "px' width='" . strval($image->width) . "px'><param value='#000000' name='bgcolor'><param name='allowFullScreen' value='true'><param value='high' name='quality'><param value='opaque' name='wmode'><param value='source=$ilink&type=video&streamtype=file&controltype=0' name='flashvars'></object>\");
 | ||||||
| } | } | ||||||
| else {	 | else {	 | ||||||
| 		document.write(\"<video controls='controls' autoplay='autoplay'>\");
 | 		document.write(\"<video controls autoplay loop'>\");
 | ||||||
| 		document.write(\"<source src='" . make_link("/image/" . $image->id) . "' type='video/mp4' />\");
 | 		document.write(\"<source src='" . make_link("/image/" . $image->id) . "' type='video/mp4' />\");
 | ||||||
| 		document.write(\"<object data='$data_href/lib/Jaris/bin/JarisFLVPlayer.swf' id='VideoPlayer' type='application/x-shockwave-flash' height='" . strval($image->height + 1). "px' width='" . strval($image->width) . "px'><param value='#000000' name='bgcolor'><param name='allowFullScreen' value='true'><param value='high' name='quality'><param value='opaque' name='wmode'><param value='source=$ilink&type=video&streamtype=file&controltype=0' name='flashvars'></object>\");
 | 		document.write(\"<object data='{$data_href}/lib/Jaris/bin/JarisFLVPlayer.swf' id='VideoPlayer' type='application/x-shockwave-flash' height='" . strval($image->height + 1). "px' width='" . strval($image->width) . "px'><param value='#000000' name='bgcolor'><param name='allowFullScreen' value='true'><param value='high' name='quality'><param value='opaque' name='wmode'><param value='source=$ilink&type=video&streamtype=file&controltype=0' name='flashvars'></object>\");
 | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| <noscript>Javascript appears to be disabled. Please enable it and try again.</noscript>";
 | <noscript>Javascript appears to be disabled. Please enable it and try again.</noscript>";
 | ||||||
| 		} elseif ($ext == "flv") { | 		} elseif ($ext == "flv") { | ||||||
| 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br><object data='$data_href/lib/Jaris/bin/JarisFLVPlayer.swf' id='VideoPlayer' type='application/x-shockwave-flash' height='" . strval($image->height + 1). "px' width='" . strval($image->width) . "px'><param value='#000000' name='bgcolor'><param name='allowFullScreen' value='true'><param value='high' name='quality'><param value='opaque' name='wmode'><param value='source=$ilink&type=video&streamtype=file&controltype=0' name='flashvars'></object>"; | 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br/>
 | ||||||
|  | 			<object data='{$data_href}/lib/Jaris/bin/JarisFLVPlayer.swf' id='VideoPlayer' type='application/x-shockwave-flash' height='" . strval($image->height + 1). "px' width='" . strval($image->width) . "px'> | ||||||
|  | 			<param value='#000000' name='bgcolor'> | ||||||
|  | 			<param name='allowFullScreen' value='true'> | ||||||
|  | 			<param value='high' name='quality'> | ||||||
|  | 			<param value='opaque' name='wmode'> | ||||||
|  | 			<param value='source={$ilink}&type=video&streamtype=file&controltype=0' name='flashvars'> | ||||||
|  | 			</object>";
 | ||||||
| 		} elseif ($ext == "ogv") { | 		} elseif ($ext == "ogv") { | ||||||
| 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br><video controls='controls' autoplay='autoplay'>
 | 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br/>
 | ||||||
|  | 			<video controls autoplay loop> | ||||||
| 			<source src='" . make_link("/image/" . $image->id) . "' type='video/ogg' /> | 			<source src='" . make_link("/image/" . $image->id) . "' type='video/ogg' /> | ||||||
| 			</video>";
 | 			</video>";
 | ||||||
| 		} elseif ($ext == "webm") { | 		} elseif ($ext == "webm") { | ||||||
| 			$html = "Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br><video controls='controls' autoplay='autoplay'>
 | 			$ie_only = "<!--[if IE]><p>To view webm files with IE, please <a href='http://tools.google.com/dlpage/webmmf/' target='_blank'>download this plugin</a>.</p><![endif]-->"; | ||||||
|  | 			$html = $ie_only ."Video not playing? <a href='" . $image->parse_link_template(make_link('image/$id/$id%20-%20$tags.$ext')) . "'>Click here</a> to download the file.<br/>
 | ||||||
|  | 			<video controls autoplay loop> | ||||||
| 			<source src='" . make_link("/image/" . $image->id) . "' type='video/webm' /> | 			<source src='" . make_link("/image/" . $image->id) . "' type='video/webm' /> | ||||||
| 			</video>";
 | 			</video>";
 | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -12,15 +12,17 @@ | |||||||
|  * An image is being added to the database. |  * An image is being added to the database. | ||||||
|  */ |  */ | ||||||
| class ImageAdditionEvent extends Event { | class ImageAdditionEvent extends Event { | ||||||
| 	var $user, $image; | 	var $user; | ||||||
|  | 	/** @var \Image */ | ||||||
|  | 	public $image; | ||||||
| 	 | 	 | ||||||
| 	/** | 	/** | ||||||
| 	 * Inserts a new image into the database with its associated | 	 * Inserts a new image into the database with its associated | ||||||
| 	 * information. Also calls TagSetEvent to set the tags for | 	 * information. Also calls TagSetEvent to set the tags for | ||||||
| 	 * this new image. | 	 * this new image. | ||||||
| 	 * | 	 * | ||||||
| 	 * @sa TagSetEvent | 	 * @see TagSetEvent | ||||||
| 	 * @param $image Image	The new image to add. | 	 * @param Image $image The new image to add. | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct(Image $image) { | 	public function __construct(Image $image) { | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| @ -39,14 +41,16 @@ class ImageAdditionException extends SCoreException { | |||||||
|  * An image is being deleted. |  * An image is being deleted. | ||||||
|  */ |  */ | ||||||
| class ImageDeletionEvent extends Event { | class ImageDeletionEvent extends Event { | ||||||
| 	var $image; | 	/** @var \Image */ | ||||||
|  | 	public $image; | ||||||
| 	 | 	 | ||||||
| 	/** | 	/** | ||||||
| 	 * Deletes an image. | 	 * Deletes an image. | ||||||
|  | 	 * | ||||||
| 	 * Used by things like tags and comments handlers to | 	 * Used by things like tags and comments handlers to | ||||||
| 	 * clean out related rows in their tables. | 	 * clean out related rows in their tables. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param $image Image	The image being deleted | 	 * @param Image $image The image being deleted. | ||||||
| 	*/ | 	*/ | ||||||
| 	public function __construct(Image $image) { | 	public function __construct(Image $image) { | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| @ -57,18 +61,20 @@ class ImageDeletionEvent extends Event { | |||||||
|  * An image is being replaced. |  * An image is being replaced. | ||||||
|  */ |  */ | ||||||
| class ImageReplaceEvent extends Event { | class ImageReplaceEvent extends Event { | ||||||
| 	var $id, $image; | 	/** @var int */ | ||||||
|  | 	public $id; | ||||||
|  | 	/** @var \Image */ | ||||||
|  | 	public $image; | ||||||
| 	 | 	 | ||||||
| 	/** | 	/** | ||||||
| 	 * Replaces an image. | 	 * Replaces an image. | ||||||
|  | 	 * | ||||||
| 	 * Updates an existing ID in the database to use a new image | 	 * Updates an existing ID in the database to use a new image | ||||||
| 	 * file, leaving the tags and such unchanged. Also removes  | 	 * file, leaving the tags and such unchanged. Also removes  | ||||||
| 	 * the old image file and thumbnail from the disk. | 	 * the old image file and thumbnail from the disk. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param $id | 	 * @param int $id The ID of the image to replace. | ||||||
| 	 *   The ID of the image to replace | 	 * @param Image $image The image object of the new image to use. | ||||||
| 	 * @param $image |  | ||||||
| 	 *   The image object of the new image to use |  | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct(/*int*/ $id, Image $image) { | 	public function __construct(/*int*/ $id, Image $image) { | ||||||
| 		$this->id = $id; | 		$this->id = $id; | ||||||
| @ -77,8 +83,12 @@ class ImageReplaceEvent extends Event { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class ImageReplaceException extends SCoreException { | class ImageReplaceException extends SCoreException { | ||||||
| 	var $error; | 	/** @var string */ | ||||||
|  | 	public $error; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $error | ||||||
|  | 	 */ | ||||||
| 	public function __construct(/*string*/ $error) { | 	public function __construct(/*string*/ $error) { | ||||||
| 		$this->error = $error; | 		$this->error = $error; | ||||||
| 	} | 	} | ||||||
| @ -88,14 +98,19 @@ class ImageReplaceException extends SCoreException { | |||||||
|  * Request a thumbnail be made for an image object. |  * Request a thumbnail be made for an image object. | ||||||
|  */ |  */ | ||||||
| class ThumbnailGenerationEvent extends Event { | class ThumbnailGenerationEvent extends Event { | ||||||
| 	var $hash, $type, $force; | 	/** @var string */ | ||||||
|  | 	public $hash; | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $type; | ||||||
|  | 	/** @var bool */ | ||||||
|  | 	public $force; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Request a thumbnail be made for an image object | 	 * Request a thumbnail be made for an image object | ||||||
| 	 * | 	 * | ||||||
| 	 * @param $hash	string The unique hash of the image | 	 * @param string $hash The unique hash of the image | ||||||
| 	 * @param $type	string The type of the image | 	 * @param string $type The type of the image | ||||||
| 	 * @param $force boolean Regenerate the thumbnail even if one already exists | 	 * @param bool $force Regenerate the thumbnail even if one already exists | ||||||
| 	 */ | 	 */ | ||||||
| 	public function __construct($hash, $type, $force=false) { | 	public function __construct($hash, $type, $force=false) { | ||||||
| 		$this->hash = $hash; | 		$this->hash = $hash; | ||||||
| @ -112,14 +127,27 @@ class ThumbnailGenerationEvent extends Event { | |||||||
|  *   $image    -- the image who's link is being parsed |  *   $image    -- the image who's link is being parsed | ||||||
|  */ |  */ | ||||||
| class ParseLinkTemplateEvent extends Event { | class ParseLinkTemplateEvent extends Event { | ||||||
| 	var $link, $original, $image; | 	/** @var string */ | ||||||
|  | 	public $link; | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $original; | ||||||
|  | 	/** @var \Image */ | ||||||
|  | 	public $image; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $link The formatted link | ||||||
|  | 	 * @param Image $image The image who's link is being parsed | ||||||
|  | 	 */ | ||||||
| 	public function __construct($link, Image $image) { | 	public function __construct($link, Image $image) { | ||||||
| 		$this->link = $link; | 		$this->link = $link; | ||||||
| 		$this->original = $link; | 		$this->original = $link; | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $needle | ||||||
|  | 	 * @param string $replace | ||||||
|  | 	 */ | ||||||
| 	public function replace($needle, $replace) { | 	public function replace($needle, $replace) { | ||||||
| 		$this->link = str_replace($needle, $replace, $this->link); | 		$this->link = str_replace($needle, $replace, $this->link); | ||||||
| 	} | 	} | ||||||
| @ -189,8 +217,7 @@ class ImageIO extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { | 	public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { | ||||||
| 		global $user; | 		global $user, $config; | ||||||
| 		global $config; |  | ||||||
| 		 | 		 | ||||||
| 		if($user->can("delete_image")) { | 		if($user->can("delete_image")) { | ||||||
| 			$event->add_part($this->theme->get_deleter_html($event->image->id)); | 			$event->add_part($this->theme->get_deleter_html($event->image->id)); | ||||||
| @ -277,6 +304,11 @@ class ImageIO extends Extension { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // add image {{{
 | // add image {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return null | ||||||
|  | 	 * @throws ImageAdditionException | ||||||
|  | 	 */ | ||||||
| 	private function add_image(Image $image) { | 	private function add_image(Image $image) { | ||||||
| 		global $page, $user, $database, $config; | 		global $page, $user, $database, $config; | ||||||
| 
 | 
 | ||||||
| @ -346,6 +378,10 @@ class ImageIO extends Extension { | |||||||
| // }}}  end add
 | // }}}  end add
 | ||||||
| 
 | 
 | ||||||
| // fetch image {{{
 | // fetch image {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param string $type | ||||||
|  | 	 */ | ||||||
| 	private function send_file($image_id, $type) { | 	private function send_file($image_id, $type) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -398,6 +434,11 @@ class ImageIO extends Extension { | |||||||
| // }}} end fetch
 | // }}} end fetch
 | ||||||
| 
 | 
 | ||||||
| // replace image {{{
 | // replace image {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $id | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @throws ImageReplaceException | ||||||
|  | 	 */ | ||||||
| 	private function replace_image($id, $image) { | 	private function replace_image($id, $image) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -159,23 +159,39 @@ | |||||||
|  * Signal that a search term needs parsing |  * Signal that a search term needs parsing | ||||||
|  */ |  */ | ||||||
| class SearchTermParseEvent extends Event { | class SearchTermParseEvent extends Event { | ||||||
| 	var $term = null; | 	/** @var null|string  */ | ||||||
| 	var $context = null; | 	public $term = null; | ||||||
| 	var $querylets = array(); | 	/** @var null|array */ | ||||||
|  | 	public $context = null; | ||||||
|  | 	/** @var \Querylet[] */ | ||||||
|  | 	public $querylets = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string|null $term | ||||||
|  | 	 * @param array|null $context | ||||||
|  | 	 */ | ||||||
| 	public function __construct($term, $context) { | 	public function __construct($term, $context) { | ||||||
| 		$this->term = $term; | 		$this->term = $term; | ||||||
| 		$this->context = $context; | 		$this->context = $context; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	public function is_querylet_set() { | 	public function is_querylet_set() { | ||||||
| 		return (count($this->querylets) > 0); | 		return (count($this->querylets) > 0); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return \Querylet[] | ||||||
|  | 	 */ | ||||||
| 	public function get_querylets() { | 	public function get_querylets() { | ||||||
| 		return $this->querylets; | 		return $this->querylets; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param \Querylet $q | ||||||
|  | 	 */ | ||||||
| 	public function add_querylet($q) { | 	public function add_querylet($q) { | ||||||
| 		$this->querylets[] = $q; | 		$this->querylets[] = $q; | ||||||
| 	} | 	} | ||||||
| @ -185,13 +201,23 @@ class SearchTermParseException extends SCoreException { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class PostListBuildingEvent extends Event { | class PostListBuildingEvent extends Event { | ||||||
| 	var $search_terms = null; | 	/** @var null|array */ | ||||||
| 	var $parts = array(); | 	public $search_terms = null; | ||||||
| 
 | 
 | ||||||
|  | 	/** @var array */ | ||||||
|  | 	public $parts = array(); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array|null $search | ||||||
|  | 	 */ | ||||||
| 	public function __construct($search) { | 	public function __construct($search) { | ||||||
| 		$this->search_terms = $search; | 		$this->search_terms = $search; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $html | ||||||
|  | 	 * @param int $position | ||||||
|  | 	 */ | ||||||
| 	public function add_control(/*string*/ $html, /*int*/ $position=50) { | 	public function add_control(/*string*/ $html, /*int*/ $position=50) { | ||||||
| 		while(isset($this->parts[$position])) $position++; | 		while(isset($this->parts[$position])) $position++; | ||||||
| 		$this->parts[$position] = $html; | 		$this->parts[$position] = $html; | ||||||
| @ -234,10 +260,10 @@ class Index extends Extension { | |||||||
| 				#log_debug("index", "Search for ".implode(" ", $search_terms), false, array("terms"=>$search_terms));
 | 				#log_debug("index", "Search for ".implode(" ", $search_terms), false, array("terms"=>$search_terms));
 | ||||||
| 				$total_pages = Image::count_pages($search_terms); | 				$total_pages = Image::count_pages($search_terms); | ||||||
| 				if(SPEED_HAX && $count_search_terms === 0 && ($page_number < 10)) { // extra caching for the first few post/list pages
 | 				if(SPEED_HAX && $count_search_terms === 0 && ($page_number < 10)) { // extra caching for the first few post/list pages
 | ||||||
| 					$images = $database->cache->get("post-list-$page_number"); | 					$images = $database->cache->get("post-list:$page_number"); | ||||||
| 					if(!$images) { | 					if(!$images) { | ||||||
| 						$images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); | 						$images = Image::find_images(($page_number-1)*$page_size, $page_size, $search_terms); | ||||||
| 						$database->cache->set("post-list-$page_number", $images, 600); | 						$database->cache->set("post-list:$page_number", $images, 600); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				else { | 				else { | ||||||
|  | |||||||
| @ -28,37 +28,13 @@ and of course start organising your images :-) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function display_page(Page $page, $images) { | 	public function display_page(Page $page, $images) { | ||||||
| 		global $config; | 		$this->display_page_header($page, $images); | ||||||
| 
 |  | ||||||
| 		if(count($this->search_terms) == 0) { |  | ||||||
| 			$query = null; |  | ||||||
| 			$page_title = $config->get_string('title'); |  | ||||||
| 		} |  | ||||||
| 		else { |  | ||||||
| 			$search_string = implode(' ', $this->search_terms); |  | ||||||
| 			$query = url_escape($search_string); |  | ||||||
| 			$page_title = html_escape($search_string); |  | ||||||
| 			if(count($images) > 0) { |  | ||||||
| 				$page->set_subheading("Page {$this->page_number} / {$this->total_pages}"); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if($this->page_number > 1 || count($this->search_terms) > 0) { |  | ||||||
| 			// $page_title .= " / $page_number";
 |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		$nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); | 		$nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); | ||||||
| 		$page->set_title($page_title); |  | ||||||
| 		$page->set_heading($page_title); |  | ||||||
| 		$page->add_block(new Block("Navigation", $nav, "left", 0)); | 		$page->add_block(new Block("Navigation", $nav, "left", 0)); | ||||||
|  | 
 | ||||||
| 		if(count($images) > 0) { | 		if(count($images) > 0) { | ||||||
| 			if($query) { | 			$this->display_page_images($page, $images); | ||||||
| 				$page->add_block(new Block("Images", $this->build_table($images, "#search=$query"), "main", 10, "image-list")); |  | ||||||
| 				$this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages); |  | ||||||
| 			} |  | ||||||
| 			else { |  | ||||||
| 				$page->add_block(new Block("Images", $this->build_table($images, null), "main", 10, "image-list")); |  | ||||||
| 				$this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages); |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			$this->display_error(404, "No Images Found", "No images were found to match the search criteria"); | 			$this->display_error(404, "No Images Found", "No images were found to match the search criteria"); | ||||||
| @ -105,5 +81,36 @@ and of course start organising your images :-) | |||||||
| 		$table .= "</div>"; | 		$table .= "</div>"; | ||||||
| 		return $table; | 		return $table; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	protected function display_page_header(Page $page, $images) { | ||||||
|  | 		global $config; | ||||||
|  | 
 | ||||||
|  | 		if (count($this->search_terms) == 0) { | ||||||
|  | 			$page_title = $config->get_string('title'); | ||||||
|  | 		} else { | ||||||
|  | 			$search_string = implode(' ', $this->search_terms); | ||||||
|  | 			$page_title = html_escape($search_string); | ||||||
|  | 			if (count($images) > 0) { | ||||||
|  | 				$page->set_subheading("Page {$this->page_number} / {$this->total_pages}"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if ($this->page_number > 1 || count($this->search_terms) > 0) { | ||||||
|  | 			// $page_title .= " / $page_number";
 | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		$page->set_title($page_title); | ||||||
|  | 		$page->set_heading($page_title); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	protected function display_page_images(Page $page, $images) { | ||||||
|  | 		if (count($this->search_terms) > 0) { | ||||||
|  | 			$query = url_escape(implode(' ', $this->search_terms)); | ||||||
|  | 			$page->add_block(new Block("Images", $this->build_table($images, "#search=$query"), "main", 10, "image-list")); | ||||||
|  | 			$this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages); | ||||||
|  | 		} else { | ||||||
|  | 			$page->add_block(new Block("Images", $this->build_table($images, null), "main", 10, "image-list")); | ||||||
|  | 			$this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								ext/notes/border-h.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ext/notes/border-h.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 72 B | 
							
								
								
									
										
											BIN
										
									
								
								ext/notes/border-v.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ext/notes/border-v.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 72 B | 
| @ -238,8 +238,11 @@ class Notes extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE GET ALL NOTES FOR DISPLAYED IMAGE | 	 * HERE WE GET ALL NOTES FOR DISPLAYED IMAGE. | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $imageID | ||||||
|  | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_notes($imageID) { | 	private function get_notes($imageID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -347,7 +350,6 @@ class Notes extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	/* | 	/* | ||||||
| 	* HERE WE DELETE THE NOTE | 	* HERE WE DELETE THE NOTE | ||||||
| 	*/ | 	*/ | ||||||
| @ -400,13 +402,15 @@ class Notes extends Extension { | |||||||
| 		log_info("notes", "Requests deleted from {$image_id} by {$user->name}"); | 		log_info("notes", "Requests deleted from {$image_id} by {$user->name}"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		 | 	/** | ||||||
| 		 |  | ||||||
| 	/* |  | ||||||
| 	 * HERE WE ALL IMAGES THAT HAVE NOTES | 	 * HERE WE ALL IMAGES THAT HAVE NOTES | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_notes_list($event) { | 	private function get_notes_list(PageRequestEvent $event) { | ||||||
|  | 		global $database, $config; | ||||||
|  | 
 | ||||||
| 		$pageNumber = $event->get_arg(1); | 		$pageNumber = $event->get_arg(1); | ||||||
|  | 
 | ||||||
| 		if(is_null($pageNumber) || !is_numeric($pageNumber)) | 		if(is_null($pageNumber) || !is_numeric($pageNumber)) | ||||||
| 		$pageNumber = 0; | 		$pageNumber = 0; | ||||||
| 		else if ($pageNumber <= 0) | 		else if ($pageNumber <= 0) | ||||||
| @ -414,13 +418,10 @@ class Notes extends Extension { | |||||||
| 		else | 		else | ||||||
| 		$pageNumber--; | 		$pageNumber--; | ||||||
| 
 | 
 | ||||||
|             global $config; |  | ||||||
|              |  | ||||||
| 		$notesPerPage = $config->get_int('notesNotesPerPage'); | 		$notesPerPage = $config->get_int('notesNotesPerPage'); | ||||||
| 	 | 	 | ||||||
| 				 |  | ||||||
| 		//$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=?", array($poolID));
 | 		//$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=?", array($poolID));
 | ||||||
| 		global $database; | 
 | ||||||
| 		$get_notes = " | 		$get_notes = " | ||||||
| 			SELECT DISTINCT image_id ".
 | 			SELECT DISTINCT image_id ".
 | ||||||
| 			"FROM notes ". | 			"FROM notes ". | ||||||
| @ -441,13 +442,15 @@ class Notes extends Extension { | |||||||
| 		$this->theme->display_note_list($images, $pageNumber + 1, $totalPages); | 		$this->theme->display_note_list($images, $pageNumber + 1, $totalPages); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	 | 	/** | ||||||
| 	 |  | ||||||
| 	/* |  | ||||||
| 	 * HERE WE GET ALL NOTE REQUESTS | 	 * HERE WE GET ALL NOTE REQUESTS | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_notes_requests($event) { | 	private function get_notes_requests(PageRequestEvent $event) { | ||||||
|  | 		global $config; | ||||||
|  | 
 | ||||||
| 		$pageNumber = $event->get_arg(1); | 		$pageNumber = $event->get_arg(1); | ||||||
|  | 
 | ||||||
| 		if(is_null($pageNumber) || !is_numeric($pageNumber)) | 		if(is_null($pageNumber) || !is_numeric($pageNumber)) | ||||||
| 			$pageNumber = 0; | 			$pageNumber = 0; | ||||||
| 		else if ($pageNumber <= 0) | 		else if ($pageNumber <= 0) | ||||||
| @ -455,8 +458,6 @@ class Notes extends Extension { | |||||||
| 		else | 		else | ||||||
| 			$pageNumber--; | 			$pageNumber--; | ||||||
| 
 | 
 | ||||||
|             global $config; |  | ||||||
|              |  | ||||||
| 		$requestsPerPage = $config->get_int('notesRequestsPerPage'); | 		$requestsPerPage = $config->get_int('notesRequestsPerPage'); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -503,11 +504,11 @@ class Notes extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	 | 	/** | ||||||
| 	/* |  | ||||||
| 	 * HERE WE GET ALL HISTORIES. | 	 * HERE WE GET ALL HISTORIES. | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_histories($event){ | 	private function get_histories(PageRequestEvent $event){ | ||||||
| 		$pageNumber = $event->get_arg(1); | 		$pageNumber = $event->get_arg(1); | ||||||
|             if(is_null($pageNumber) || !is_numeric($pageNumber)) |             if(is_null($pageNumber) || !is_numeric($pageNumber)) | ||||||
|                 $pageNumber = 0; |                 $pageNumber = 0; | ||||||
| @ -535,11 +536,11 @@ class Notes extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	 | 	/** | ||||||
| 	/* |  | ||||||
| 	 * HERE WE THE HISTORY FOR A SPECIFIC NOTE. | 	 * HERE WE THE HISTORY FOR A SPECIFIC NOTE. | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_history($event){ | 	private function get_history(PageRequestEvent $event){ | ||||||
| 		$noteID = $event->get_arg(1); | 		$noteID = $event->get_arg(1); | ||||||
| 		$pageNumber = $event->get_arg(2); | 		$pageNumber = $event->get_arg(2); | ||||||
|             if(is_null($pageNumber) || !is_numeric($pageNumber)) |             if(is_null($pageNumber) || !is_numeric($pageNumber)) | ||||||
| @ -567,13 +568,13 @@ class Notes extends Extension { | |||||||
| 		$this->theme->display_history($histories, $pageNumber + 1, $totalPages); | 		$this->theme->display_history($histories, $pageNumber + 1, $totalPages); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	 | 	/** | ||||||
| 	 | 	 * HERE GO BACK IN HISTORY AND SET THE OLD NOTE. IF WAS REMOVED WE RE-ADD IT. | ||||||
| 	/* | 	 * @param int $noteID | ||||||
| 	* HERE GO BACK IN HISTORY AND SET THE OLD NOTE. IF WAS REMOVED WE READD IT. | 	 * @param int $reviewID | ||||||
| 	 */ | 	 */ | ||||||
| 	private function revert_history($noteID, $reviewID){ | 	private function revert_history($noteID, $reviewID){ | ||||||
| 		global $user, $database; | 		global $database; | ||||||
| 		 | 		 | ||||||
| 		$history = $database->get_row("SELECT * FROM note_histories WHERE note_id = ? AND review_id = ?",array($noteID, $reviewID)); | 		$history = $database->get_row("SELECT * FROM note_histories WHERE note_id = ? AND review_id = ?",array($noteID, $reviewID)); | ||||||
| 		 | 		 | ||||||
| @ -596,7 +597,6 @@ class Notes extends Extension { | |||||||
| 						   "WHERE image_id = ? AND id = ?", array(1, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText, $imageID, $noteID)); | 						   "WHERE image_id = ? AND id = ?", array(1, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText, $imageID, $noteID)); | ||||||
| 								   | 								   | ||||||
| 		$this->add_history($noteEnable, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText); | 		$this->add_history($noteEnable, $noteID, $imageID, $noteX1, $noteY1, $noteHeight, $noteWidth, $noteText); | ||||||
| 		 |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,7 +2,9 @@ | |||||||
| 
 | 
 | ||||||
| $(function() { | $(function() { | ||||||
| 	if(window.notes) { | 	if(window.notes) { | ||||||
|  | 		$('#main_image').load(function(){ | ||||||
| 			$('#main_image').imgNotes({notes: window.notes}); | 			$('#main_image').imgNotes({notes: window.notes}); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	$('#cancelnote').click(function(){ | 	$('#cancelnote').click(function(){ | ||||||
|  | |||||||
| @ -33,3 +33,45 @@ | |||||||
| #noteform textarea, #noteEditForm textarea { | #noteform textarea, #noteEditForm textarea { | ||||||
| 	width: 100%; | 	width: 100%; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * imgAreaSelect default style | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | .imgareaselect-border1 { | ||||||
|  | 	background: url(border-v.gif) repeat-y left top; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-border2 { | ||||||
|  |     background: url(border-h.gif) repeat-x left top; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-border3 { | ||||||
|  |     background: url(border-v.gif) repeat-y right top; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-border4 { | ||||||
|  |     background: url(border-h.gif) repeat-x left bottom; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-border1, .imgareaselect-border2, | ||||||
|  | .imgareaselect-border3, .imgareaselect-border4 { | ||||||
|  |     filter: alpha(opacity=50); | ||||||
|  | 	opacity: 0.5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-handle { | ||||||
|  |     background-color: #fff; | ||||||
|  |     border: solid 1px #000; | ||||||
|  |     filter: alpha(opacity=50); | ||||||
|  |     opacity: 0.5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-outer { | ||||||
|  |     /*background-color: #000;*/ | ||||||
|  |     filter: alpha(opacity=50); | ||||||
|  |     opacity: 0.5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .imgareaselect-selection {   | ||||||
|  | } | ||||||
| @ -284,6 +284,11 @@ class NumericScore extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param int $user_id | ||||||
|  | 	 * @param int $score | ||||||
|  | 	 */ | ||||||
| 	private function add_vote(/*int*/ $image_id, /*int*/ $user_id, /*int*/ $score) { | 	private function add_vote(/*int*/ $image_id, /*int*/ $user_id, /*int*/ $score) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$database->execute( | 		$database->execute( | ||||||
|  | |||||||
| @ -58,7 +58,7 @@ class NumericScoreTheme extends Themelet { | |||||||
| 			<input type='submit' value='Delete all votes by this user'> | 			<input type='submit' value='Delete all votes by this user'> | ||||||
| 			</form> | 			</form> | ||||||
| 		";
 | 		";
 | ||||||
| 		$page->add_block(new Block("Votes", $html, "main", 60)); | 		$page->add_block(new Block("Votes", $html, "main", 80)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function view_popular($images, $dte) { | 	public function view_popular($images, $dte) { | ||||||
|  | |||||||
| @ -197,7 +197,7 @@ class PrivMsg extends Extension { | |||||||
| 	private function count_pms(User $user) { | 	private function count_pms(User $user) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| 		$count = $database->cache->get("pm-count-{$user->id}"); | 		$count = $database->cache->get("pm-count:{$user->id}"); | ||||||
| 		if(is_null($count) || $count === false) { | 		if(is_null($count) || $count === false) { | ||||||
| 			$count = $database->get_one(" | 			$count = $database->get_one(" | ||||||
| 					SELECT count(*) | 					SELECT count(*) | ||||||
| @ -205,7 +205,7 @@ class PrivMsg extends Extension { | |||||||
| 					WHERE to_id = :to_id | 					WHERE to_id = :to_id | ||||||
| 					AND is_read = :is_read | 					AND is_read = :is_read | ||||||
| 			", array("to_id" => $user->id, "is_read" => "N"));
 | 			", array("to_id" => $user->id, "is_read" => "N"));
 | ||||||
| 			$database->cache->set("pm-count-{$user->id}", $count, 600); | 			$database->cache->set("pm-count:{$user->id}", $count, 600); | ||||||
| 		} | 		} | ||||||
| 		return $count; | 		return $count; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ class PrivMsgTheme extends Themelet { | |||||||
| 				</tbody> | 				</tbody> | ||||||
| 			</table> | 			</table> | ||||||
| 		";
 | 		";
 | ||||||
| 		$page->add_block(new Block("Private Messages", $html, "main", 10, "private-messages")); | 		$page->add_block(new Block("Private Messages", $html, "main", 40, "private-messages")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function display_composer(Page $page, User $from, User $to, $subject="") { | 	public function display_composer(Page $page, User $from, User $to, $subject="") { | ||||||
| @ -59,7 +59,7 @@ $auth | |||||||
| </table> | </table> | ||||||
| </form> | </form> | ||||||
| EOD; | EOD; | ||||||
| 		$page->add_block(new Block("Write a PM", $html, "main", 20)); | 		$page->add_block(new Block("Write a PM", $html, "main", 50)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function display_message(Page $page, User $from, User $to, PM $pm) { | 	public function display_message(Page $page, User $from, User $to, PM $pm) { | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| <?php | <?php | ||||||
| /** | /** | ||||||
|  * Name: Pools System |  * Name: Pools System | ||||||
|  * Author: Sein Kraft <mail@seinkraft.info>, jgen <jgen.tech@gmail.com> |  * Author: Sein Kraft <mail@seinkraft.info>, jgen <jgen.tech@gmail.com>, Daku <admin@codeanimu.net> | ||||||
|  * License: GPLv2 |  * License: GPLv2 | ||||||
|  * Description: Allow users to create groups of images and order them. |  * Description: Allow users to create groups of images and order them. | ||||||
|  * Documentation: This extension allows users to created named groups of |  * Documentation: This extension allows users to created named groups of | ||||||
| @ -13,8 +13,12 @@ | |||||||
|  * This class is just a wrapper around SCoreException. |  * This class is just a wrapper around SCoreException. | ||||||
|  */ |  */ | ||||||
| class PoolCreationException extends SCoreException { | class PoolCreationException extends SCoreException { | ||||||
| 	var $error; | 	/** @var string */ | ||||||
|  | 	public $error; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $error | ||||||
|  | 	 */ | ||||||
| 	public function __construct($error) { | 	public function __construct($error) { | ||||||
| 		$this->error = $error; | 		$this->error = $error; | ||||||
| 	} | 	} | ||||||
| @ -76,6 +80,13 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 			$config->set_int("ext_pools_version", 2); | 			$config->set_int("ext_pools_version", 2); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if ($config->get_int("ext_pools_version") < 3){ | ||||||
|  | 			$config->set_bool("poolsShowNavLinks","N"); //A $config->rename() function would be nice here...
 | ||||||
|  | 			$config->set_bool("poolsAutoIncrementOrder","N"); | ||||||
|  | 
 | ||||||
|  | 			$config->set_int("ext_pools_version", 3); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Add a block to the Board Config / Setup
 | 	// Add a block to the Board Config / Setup
 | ||||||
| @ -86,16 +97,17 @@ class Pools extends Extension { | |||||||
| 		$sb->add_int_option("poolsListsPerPage", "<br>Index list items per page: "); | 		$sb->add_int_option("poolsListsPerPage", "<br>Index list items per page: "); | ||||||
| 		$sb->add_int_option("poolsUpdatedPerPage", "<br>Updated list items per page: "); | 		$sb->add_int_option("poolsUpdatedPerPage", "<br>Updated list items per page: "); | ||||||
| 		$sb->add_bool_option("poolsInfoOnViewImage", "<br>Show pool info on image: "); | 		$sb->add_bool_option("poolsInfoOnViewImage", "<br>Show pool info on image: "); | ||||||
| 		$sb->add_bool_option("poolsShowNextLink", "<br>Show 'Next' link when viewing pool images: "); | 		$sb->add_bool_option("poolsShowNavLinks", "<br>Show 'Prev' & 'Next' links when viewing pool images: "); | ||||||
|  | 		$sb->add_bool_option("poolsAutoIncrementOrder", "<br>Autoincrement order when post is added to pool:"); | ||||||
| 		//$sb->add_bool_option("poolsAdderOnViewImage", "<br>Show pool adder on image: ");
 | 		//$sb->add_bool_option("poolsAdderOnViewImage", "<br>Show pool adder on image: ");
 | ||||||
|  | 
 | ||||||
| 		$event->panel->add_block($sb); | 		$event->panel->add_block($sb); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		global $config, $page, $user; | 		global $page, $user; | ||||||
| 		 | 		 | ||||||
| 		if ($event->page_matches("pool")) { | 		if ($event->page_matches("pool")) { | ||||||
| 
 |  | ||||||
| 			$pool_id = 0; | 			$pool_id = 0; | ||||||
| 			$pool = array(); | 			$pool = array(); | ||||||
| 
 | 
 | ||||||
| @ -249,30 +261,27 @@ class Pools extends Extension { | |||||||
| 	 * to the Next image in the pool. | 	 * to the Next image in the pool. | ||||||
| 	 */ | 	 */ | ||||||
| 	public function onDisplayingImage(DisplayingImageEvent $event) { | 	public function onDisplayingImage(DisplayingImageEvent $event) { | ||||||
| 		global $config, $database, $page; | 		global $config; | ||||||
| 
 | 
 | ||||||
| 		if($config->get_bool("poolsInfoOnViewImage")) { | 		if($config->get_bool("poolsInfoOnViewImage")) { | ||||||
| 			$imageID = $event->image->id; | 			$imageID = $event->image->id; | ||||||
| 			$poolsIDs = $this->get_pool_id($imageID); | 			$poolsIDs = $this->get_pool_id($imageID); | ||||||
| 
 | 
 | ||||||
| 			$show_next = $config->get_bool("poolsShowNextLink", false); | 			$show_nav = $config->get_bool("poolsShowNavLinks", false); | ||||||
| 
 | 
 | ||||||
| 			$linksPools = array(); | 			$navInfo = array(); | ||||||
| 			foreach($poolsIDs as $poolID) { | 			foreach($poolsIDs as $poolID) { | ||||||
| 				$pools = $this->get_pool($poolID['pool_id']); | 				$pool = $this->get_single_pool($poolID['pool_id']); | ||||||
| 				foreach ($pools as $pool){ |  | ||||||
| 					$linksPools[] = "<a href='".make_link("pool/view/".$pool['id'])."'>".html_escape($pool['title'])."</a>"; |  | ||||||
| 
 | 
 | ||||||
| 					// Optionally show a link the Next image in the Pool.
 | 				$navInfo[$pool['id']] = array(); | ||||||
| 					if ($show_next) { | 				$navInfo[$pool['id']]['info'] = $pool; | ||||||
| 						$next_image_in_pool = $this->get_next_post($pool, $imageID); | 
 | ||||||
| 						if (!empty($next_image_in_pool)) { | 				// Optionally show a link the Prev/Next image in the Pool.
 | ||||||
| 							$linksPools[] = '<a href="'.make_link('post/view/'.$next_image_in_pool).'" class="pools_next_img">Next</a>'; | 				if ($show_nav) { | ||||||
|  | 					$navInfo[$pool['id']]['nav'] = $this->get_nav_posts($pool, $imageID); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 				} | 			$this->theme->pool_info($navInfo); | ||||||
| 			} |  | ||||||
| 			$this->theme->pool_info($linksPools); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -316,19 +325,24 @@ class Pools extends Extension { | |||||||
| 	public function onTagTermParse(TagTermParseEvent $event) { | 	public function onTagTermParse(TagTermParseEvent $event) { | ||||||
| 		$matches = array(); | 		$matches = array(); | ||||||
| 
 | 
 | ||||||
| 		if(preg_match("/^pool[=|:](.*)$/i", $event->term, $matches)) { | 		if(preg_match("/^pool[=|:]([^:]*|lastcreated):?([0-9]*)$/i", $event->term, $matches)) { | ||||||
| 			global $user; | 			global $user; | ||||||
| 			$poolTag = (string) str_replace("_", " ", $matches[1]); | 			$poolTag = (string) str_replace("_", " ", $matches[1]); | ||||||
| 
 | 
 | ||||||
| 			$pool = null; | 			$pool = null; | ||||||
| 			if(ctype_digit($poolTag)){ //If only digits, assume PoolID
 | 			if($poolTag == 'lastcreated'){ | ||||||
|  | 				$pool = $this->get_last_userpool($user->id); | ||||||
|  | 			} | ||||||
|  | 			elseif(ctype_digit($poolTag)){ //If only digits, assume PoolID
 | ||||||
| 				$pool = $this->get_single_pool($poolTag); | 				$pool = $this->get_single_pool($poolTag); | ||||||
| 			}else{ //assume PoolTitle
 | 			}else{ //assume PoolTitle
 | ||||||
| 				$pool = $this->get_single_pool_from_title($poolTag); | 				$pool = $this->get_single_pool_from_title($poolTag); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 			if($pool ? $this->have_permission($user, $pool) : FALSE){ | 			if($pool ? $this->have_permission($user, $pool) : FALSE){ | ||||||
| 				$this->add_post($pool['id'], $event->id, true); | 				$image_order = ($matches[2] ?: 0); | ||||||
|  | 				$this->add_post($pool['id'], $event->id, true, $image_order); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -341,7 +355,11 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Check if the given user has permission to edit/change the pool. | 	 * Check if the given user has permission to edit/change the pool. | ||||||
|  | 	 * | ||||||
| 	 * TODO: Should the user variable be global? | 	 * TODO: Should the user variable be global? | ||||||
|  | 	 * | ||||||
|  | 	 * @param \User $user | ||||||
|  | 	 * @param array $pool | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| 	private function have_permission($user, $pool) { | 	private function have_permission($user, $pool) { | ||||||
| @ -354,8 +372,11 @@ class Pools extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE GET THE LIST OF POOLS | 	 * HERE WE GET THE LIST OF POOLS. | ||||||
|  | 	 * | ||||||
|  | 	 * @param \Page $page | ||||||
|  | 	 * @param int $pageNumber | ||||||
| 	 */ | 	 */ | ||||||
| 	private function list_pools(Page $page, /*int*/ $pageNumber) { | 	private function list_pools(Page $page, /*int*/ $pageNumber) { | ||||||
| 		global $config, $database; | 		global $config, $database; | ||||||
| @ -399,8 +420,11 @@ class Pools extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE CREATE A NEW POOL | 	 * HERE WE CREATE A NEW POOL | ||||||
|  | 	 * | ||||||
|  | 	 * @return mixed | ||||||
|  | 	 * @throws PoolCreationException | ||||||
| 	 */ | 	 */ | ||||||
| 	private function add_pool() { | 	private function add_pool() { | ||||||
| 		global $user, $database; | 		global $user, $database; | ||||||
| @ -431,8 +455,11 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Retrieve information about pools given multiple pool IDs. | 	 * Retrieve information about pools given multiple pool IDs. | ||||||
| 	 * @param $poolID Array of integers | 	 * | ||||||
| 	 * @return 2D Array | 	 * TODO: What is the difference between this and get_single_pool() other than the db query? | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $poolID Array of integers | ||||||
|  | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_pool(/*int*/ $poolID) { | 	private function get_pool(/*int*/ $poolID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -441,8 +468,8 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Retrieve information about a pool given a pool ID. | 	 * Retrieve information about a pool given a pool ID. | ||||||
| 	 * @param $poolID Integer | 	 * @param int $poolID the pool id | ||||||
| 	 * @return 2D array (with only 1 element in the one dimension) | 	 * @return array Array with only 1 element in the one dimension | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_single_pool(/*int*/ $poolID) { | 	private function get_single_pool(/*int*/ $poolID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -451,8 +478,8 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Retrieve information about a pool given a pool title. | 	 * Retrieve information about a pool given a pool title. | ||||||
| 	 * @param $poolTitle Integer | 	 * @param string $poolTitle | ||||||
| 	 * @return 2D array (with only 1 element in the one dimension) | 	 * @return array Array (with only 1 element in the one dimension) | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_single_pool_from_title(/*string*/ $poolTitle) { | 	private function get_single_pool_from_title(/*string*/ $poolTitle) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -461,32 +488,44 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get all of the pool IDs that an image is in, given an image ID. | 	 * Get all of the pool IDs that an image is in, given an image ID. | ||||||
| 	 * @param $imageID Integer | 	 * @param int $imageID Integer ID for the image | ||||||
| 	 * @return 2D array | 	 * @return array | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_pool_id(/*int*/ $imageID) { | 	private function get_pool_id(/*int*/ $imageID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		return $database->get_all("SELECT pool_id FROM pool_images WHERE image_id=:iid", array("iid"=>$imageID)); | 		return $database->get_all("SELECT pool_id FROM pool_images WHERE image_id=:iid", array("iid"=>$imageID)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Retrieve information about the last pool the given userID created | ||||||
|  | 	 * @param int $userID | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
|  | 	private function get_last_userpool(/*int*/ $userID){ | ||||||
|  | 		global $database; | ||||||
|  | 		return $database->get_row("SELECT * FROM pools WHERE user_id=:uid ORDER BY id DESC", array("uid"=>$userID)); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE GET THE IMAGES FROM THE TAG ON IMPORT | 	 * HERE WE GET THE IMAGES FROM THE TAG ON IMPORT | ||||||
|  | 	 * @param int $pool_id | ||||||
| 	 */ | 	 */ | ||||||
| 	private function import_posts(/*int*/ $pool_id) { | 	private function import_posts(/*int*/ $pool_id) { | ||||||
| 		global $page, $config, $database; | 		global $page, $config; | ||||||
| 
 | 
 | ||||||
| 		$poolsMaxResults = $config->get_int("poolsMaxImportResults", 1000); | 		$poolsMaxResults = $config->get_int("poolsMaxImportResults", 1000); | ||||||
| 		 | 		 | ||||||
| 		$images = $images = Image::find_images(0, $poolsMaxResults, Tag::explode($_POST["pool_tag"])); | 		$images = $images = Image::find_images(0, $poolsMaxResults, Tag::explode($_POST["pool_tag"])); | ||||||
| 		$this->theme->pool_result($page, $images, $pool_id); | 		$this->theme->pool_result($page, $images, $this->get_pool($pool_id)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE ADD CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY | 	 * HERE WE ADD CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY | ||||||
| 	 * | 	 * | ||||||
| 	 * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. | 	 * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. | ||||||
|  | 	 * | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	private function add_posts() { | 	private function add_posts() { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -503,11 +542,10 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 				$images .= " ".$imageID; | 				$images .= " ".$imageID; | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if(!strlen($images) == 0) { | 		if(!strlen($images) == 0) { | ||||||
| 			$count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID)); | 			$count = int_escape($database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID))); | ||||||
| 			$this->add_history($poolID, 1, $images, $count); | 			$this->add_history($poolID, 1, $images, $count); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -520,8 +558,9 @@ class Pools extends Extension { | |||||||
| 		return $poolID; | 		return $poolID; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. | 	 * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	private function order_posts() { | 	private function order_posts() { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -541,11 +580,12 @@ class Pools extends Extension { | |||||||
| 		return $poolID; | 		return $poolID; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 	/* |  | ||||||
| 	 * HERE WE REMOVE CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY | 	 * HERE WE REMOVE CHECKED IMAGES FROM POOL AND UPDATE THE HISTORY | ||||||
| 	 * | 	 * | ||||||
| 	 * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. | 	 * TODO: Fix this so that the pool ID and images are passed as Arguments to the function. | ||||||
|  | 	 * | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	private function remove_posts() { | 	private function remove_posts() { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -563,8 +603,9 @@ class Pools extends Extension { | |||||||
| 		return $poolID; | 		return $poolID; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * Allows editing of pool description. | 	 * Allows editing of pool description. | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	private function edit_description() { | 	private function edit_description() { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -580,8 +621,8 @@ class Pools extends Extension { | |||||||
| 	 * Used by add_posts() | 	 * Used by add_posts() | ||||||
| 	 * | 	 * | ||||||
| 	 * @see add_posts() | 	 * @see add_posts() | ||||||
| 	 * @param $poolID integer | 	 * @param int $poolID | ||||||
| 	 * @param $imageID integer | 	 * @param int $imageID | ||||||
| 	 * @return bool | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| 	private function check_post(/*int*/ $poolID, /*int*/ $imageID) { | 	private function check_post(/*int*/ $poolID, /*int*/ $imageID) { | ||||||
| @ -591,24 +632,47 @@ class Pools extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Gets the next successive image from a pool, given a pool ID and an image ID. | 	 * Gets the previous and next successive images from a pool, given a pool ID and an image ID. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param $pool Array for the given pool | 	 * @param array $pool Array for the given pool | ||||||
| 	 * @param $imageID Integer | 	 * @param int $imageID Integer | ||||||
| 	 * @return Integer which is the next Image ID or NULL if none. | 	 * @return array Array returning two elements (prev, next) in 1 dimension. Each returns ImageID or NULL if none. | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_next_post(/*array*/ $pool, /*int*/ $imageID) { | 	private function get_nav_posts(/*array*/ $pool, /*int*/ $imageID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| 		if (empty($pool) || empty($imageID)) | 		if (empty($pool) || empty($imageID)) | ||||||
| 			return null; | 			return null; | ||||||
| 		 | 		 | ||||||
| 		$result = $database->get_one(" | 		$result = $database->get_row(" | ||||||
|  | 						SELECT ( | ||||||
| 							SELECT image_id | 							SELECT image_id | ||||||
| 							FROM pool_images | 							FROM pool_images | ||||||
| 							WHERE pool_id = :pid | 							WHERE pool_id = :pid | ||||||
| 					AND image_order > (SELECT image_order FROM pool_images WHERE pool_id=:pid AND image_id =:iid LIMIT 1 ) | 							AND image_order < ( | ||||||
| 					ORDER BY image_order ASC LIMIT 1",
 | 								SELECT image_order | ||||||
|  | 								FROM pool_images | ||||||
|  | 								WHERE pool_id = :pid | ||||||
|  | 								AND image_id = :iid | ||||||
|  | 								LIMIT 1 | ||||||
|  | 							) | ||||||
|  | 							ORDER BY image_order DESC LIMIT 1 | ||||||
|  | 						) AS prev, | ||||||
|  | 						( | ||||||
|  | 							SELECT image_id | ||||||
|  | 							FROM pool_images | ||||||
|  | 							WHERE pool_id = :pid | ||||||
|  | 							AND image_order > ( | ||||||
|  | 								SELECT image_order | ||||||
|  | 								FROM pool_images | ||||||
|  | 								WHERE pool_id = :pid | ||||||
|  | 								AND image_id = :iid | ||||||
|  | 								LIMIT 1 | ||||||
|  | 							) | ||||||
|  | 							ORDER BY image_order ASC LIMIT 1 | ||||||
|  | 						) AS next | ||||||
|  | 
 | ||||||
|  | 						LIMIT 1",
 | ||||||
| 					array("pid"=>$pool['id'], "iid"=>$imageID) ); | 					array("pid"=>$pool['id'], "iid"=>$imageID) ); | ||||||
| 
 | 
 | ||||||
| 		if (empty($result)) { | 		if (empty($result)) { | ||||||
| @ -621,6 +685,9 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Retrieve all the images in a pool, given a pool ID. | 	 * Retrieve all the images in a pool, given a pool ID. | ||||||
|  | 	 * | ||||||
|  | 	 * @param PageRequestEvent $event | ||||||
|  | 	 * @param int $poolID | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_posts($event, /*int*/ $poolID) { | 	private function get_posts($event, /*int*/ $poolID) { | ||||||
| 		global $config, $user, $database; | 		global $config, $user, $database; | ||||||
| @ -684,8 +751,8 @@ class Pools extends Extension { | |||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * This function gets the current order of images from a given pool. | 	 * This function gets the current order of images from a given pool. | ||||||
| 	 * @param $poolID integer | 	 * @param int $poolID | ||||||
| 	 * @return Array of image objects. | 	 * @return \Image[] Array of image objects. | ||||||
| 	 */ | 	 */ | ||||||
| 	private function edit_posts(/*int*/ $poolID) { | 	private function edit_posts(/*int*/ $poolID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -702,8 +769,11 @@ class Pools extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * WE GET THE ORDER OF THE IMAGES BUT HERE WE SEND KEYS ADDED IN ARRAY TO GET THE ORDER IN THE INPUT VALUE | 	 * WE GET THE ORDER OF THE IMAGES BUT HERE WE SEND KEYS ADDED IN ARRAY TO GET THE ORDER IN THE INPUT VALUE. | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $poolID | ||||||
|  | 	 * @return \Image[] | ||||||
| 	 */ | 	 */ | ||||||
| 	private function edit_order(/*int*/ $poolID) { | 	private function edit_order(/*int*/ $poolID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -726,8 +796,10 @@ class Pools extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE NUKE ENTIRE POOL. WE REMOVE POOLS AND POSTS FROM REMOVED POOL AND HISTORIES ENTRIES FROM REMOVED POOL | 	 * HERE WE NUKE ENTIRE POOL. WE REMOVE POOLS AND POSTS FROM REMOVED POOL AND HISTORIES ENTRIES FROM REMOVED POOL. | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $poolID | ||||||
| 	 */ | 	 */ | ||||||
| 	private function nuke_pool(/*int*/ $poolID) { | 	private function nuke_pool(/*int*/ $poolID) { | ||||||
| 		global $user, $database; | 		global $user, $database; | ||||||
| @ -744,10 +816,13 @@ class Pools extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 	/* | 	 * HERE WE ADD A HISTORY ENTRY. | ||||||
| 	 * HERE WE ADD A HISTORY ENTRY | 	 * | ||||||
| 	 * FOR $action 1 (one) MEANS ADDED, 0 (zero) MEANS REMOVED | 	 * @param int $poolID | ||||||
|  | 	 * @param int $action Action=1 (one) MEANS ADDED, Action=0 (zero) MEANS REMOVED | ||||||
|  | 	 * @param string $images | ||||||
|  | 	 * @param int $count | ||||||
| 	 */ | 	 */ | ||||||
| 	private function add_history(/*int*/ $poolID, $action, $images, $count) { | 	private function add_history(/*int*/ $poolID, $action, $images, $count) { | ||||||
| 		global $user, $database; | 		global $user, $database; | ||||||
| @ -758,9 +833,9 @@ class Pools extends Extension { | |||||||
| 				array("pid"=>$poolID, "uid"=>$user->id, "act"=>$action, "img"=>$images, "count"=>$count)); | 				array("pid"=>$poolID, "uid"=>$user->id, "act"=>$action, "img"=>$images, "count"=>$count)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 	/* | 	 * HERE WE GET THE HISTORY LIST. | ||||||
| 	 * HERE WE GET THE HISTORY LIST | 	 * @param int $pageNumber | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_history(/*int*/ $pageNumber) { | 	private function get_history(/*int*/ $pageNumber) { | ||||||
| 		global $config, $database; | 		global $config, $database; | ||||||
| @ -772,7 +847,6 @@ class Pools extends Extension { | |||||||
| 		else | 		else | ||||||
| 			$pageNumber--; | 			$pageNumber--; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		$historiesPerPage = $config->get_int("poolsUpdatedPerPage"); | 		$historiesPerPage = $config->get_int("poolsUpdatedPerPage"); | ||||||
| 
 | 
 | ||||||
| 		$history = $database->get_all(" | 		$history = $database->get_all(" | ||||||
| @ -792,10 +866,9 @@ class Pools extends Extension { | |||||||
| 		$this->theme->show_history($history, $pageNumber + 1, $totalPages); | 		$this->theme->show_history($history, $pageNumber + 1, $totalPages); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 
 | 	 * HERE GO BACK IN HISTORY AND ADD OR REMOVE POSTS TO POOL. | ||||||
| 	/* | 	 * @param int $historyID | ||||||
| 	 * HERE GO BACK IN HISTORY AND ADD OR REMOVE POSTS TO POOL |  | ||||||
| 	 */ | 	 */ | ||||||
| 	private function revert_history(/*int*/ $historyID) { | 	private function revert_history(/*int*/ $historyID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -838,20 +911,31 @@ class Pools extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 
 | 	 * HERE WE ADD A SIMPLE POST FROM POOL. | ||||||
| 	/* | 	 * USED WITH FOREACH IN revert_history() & onTagTermParse(). | ||||||
| 	 * HERE WE ADD A SIMPLE POST FROM POOL | 	 * | ||||||
| 	 * USED WITH FOREACH IN revert_history() & onTagTermParse() | 	 * @param int $poolID | ||||||
|  | 	 * @param int $imageID | ||||||
|  | 	 * @param bool $history | ||||||
|  | 	 * @param int $imageOrder | ||||||
| 	 */ | 	 */ | ||||||
| 	private function add_post(/*int*/ $poolID, /*int*/ $imageID, $history=false) { | 	private function add_post(/*int*/ $poolID, /*int*/ $imageID, $history=false, $imageOrder=0) { | ||||||
| 		global $database; | 		global $database, $config; | ||||||
| 
 | 
 | ||||||
| 		if(!$this->check_post($poolID, $imageID)) { | 		if(!$this->check_post($poolID, $imageID)) { | ||||||
|  | 			if($config->get_bool("poolsAutoIncrementOrder") && $imageOrder === 0){ | ||||||
|  | 				$imageOrder = $database->get_one(" | ||||||
|  | 						SELECT CASE WHEN image_order IS NOT NULL THEN MAX(image_order) + 1 ELSE 0 END | ||||||
|  | 						FROM pool_images | ||||||
|  | 						WHERE pool_id = :pid",
 | ||||||
|  | 						array("pid"=>$poolID)); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			$database->execute(" | 			$database->execute(" | ||||||
| 					INSERT INTO pool_images (pool_id, image_id) | 					INSERT INTO pool_images (pool_id, image_id, image_order) | ||||||
| 					VALUES (:pid, :iid)",
 | 					VALUES (:pid, :iid, :ord)",
 | ||||||
| 					array("pid"=>$poolID, "iid"=>$imageID)); | 					array("pid"=>$poolID, "iid"=>$imageID, "ord"=>$imageOrder)); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID)); | 		$database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID)); | ||||||
| @ -862,11 +946,13 @@ class Pools extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 
 | 	 * HERE WE REMOVE A SIMPLE POST FROM POOL. | ||||||
| 	/* | 	 * USED WITH FOREACH IN revert_history() & onTagTermParse(). | ||||||
| 	 * HERE WE REMOVE A SIMPLE POST FROM POOL | 	 * | ||||||
| 	 * USED WITH FOREACH IN revert_history() & onTagTermParse() | 	 * @param int $poolID | ||||||
|  | 	 * @param int $imageID | ||||||
|  | 	 * @param bool $history | ||||||
| 	 */ | 	 */ | ||||||
| 	private function delete_post(/*int*/ $poolID, /*int*/ $imageID, $history=false) { | 	private function delete_post(/*int*/ $poolID, /*int*/ $imageID, $history=false) { | ||||||
| 		global $database; | 		global $database; | ||||||
|  | |||||||
							
								
								
									
										13
									
								
								ext/pools/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								ext/pools/style.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | .pools_next_img { | ||||||
|  | 	display: block; | ||||||
|  | 	font-size: 77%; | ||||||
|  | 	text-align: right; | ||||||
|  | 	float: right; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .pools_prev_img { | ||||||
|  | 	display: block; | ||||||
|  | 	font-size: 77%; | ||||||
|  | 	text-align: left; | ||||||
|  | 	float: left; | ||||||
|  | } | ||||||
| @ -3,14 +3,39 @@ | |||||||
| class PoolsTheme extends Themelet { | class PoolsTheme extends Themelet { | ||||||
| 	/** | 	/** | ||||||
| 	 * Adds a block to the panel with information on the pool(s) the image is in. | 	 * Adds a block to the panel with information on the pool(s) the image is in. | ||||||
|  | 	 * @param array Multidimensional array containing pool id, info & nav IDs. | ||||||
| 	 */ | 	 */ | ||||||
| 	public function pool_info($linksPools) { | 	public function pool_info(/*array*/ $navIDs) { | ||||||
| 		global $page; | 		global $page; | ||||||
|  | 
 | ||||||
|  | 		$linksPools = array(); | ||||||
|  | 		foreach($navIDs as $poolID => $pool){ | ||||||
|  | 			$linksPools[] = "<a href='".make_link("pool/view/".$poolID)."'>".html_escape($pool['info']['title'])."</a>"; | ||||||
|  | 
 | ||||||
|  | 			if (array_key_exists('nav', $pool)){ | ||||||
|  | 				$navlinks = ""; | ||||||
|  | 				if (!empty($pool['nav']['prev'])) { | ||||||
|  | 					$navlinks .= '<a href="'.make_link('post/view/'.$pool['nav']['prev']).'" class="pools_prev_img">Prev</a>'; | ||||||
|  | 				} | ||||||
|  | 				if (!empty($pool['nav']['next'])) { | ||||||
|  | 					$navlinks .= '<a href="'.make_link('post/view/'.$pool['nav']['next']).'" class="pools_next_img">Next</a>'; | ||||||
|  | 				} | ||||||
|  | 				if(!empty($navlinks)){ | ||||||
|  | 					$linksPools[] = $navlinks; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if(count($linksPools) > 0) { | 		if(count($linksPools) > 0) { | ||||||
| 			$page->add_block(new Block("Pools", implode("<br>", $linksPools), "left")); | 			$page->add_block(new Block("Pools", implode("<br>", $linksPools), "left")); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param array $pools | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function get_adder_html(Image $image, /*array*/ $pools) { | 	public function get_adder_html(Image $image, /*array*/ $pools) { | ||||||
| 		$h = ""; | 		$h = ""; | ||||||
| 		foreach($pools as $pool) { | 		foreach($pools as $pool) { | ||||||
| @ -27,9 +52,13 @@ class PoolsTheme extends Themelet { | |||||||
| 		return $editor; | 		return $editor; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 	/* | 	 * HERE WE SHOWS THE LIST OF POOLS. | ||||||
| 	 * HERE WE SHOWS THE LIST OF POOLS | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $pools | ||||||
|  | 	 * @param int $pageNumber | ||||||
|  | 	 * @param int $totalPages | ||||||
| 	 */ | 	 */ | ||||||
| 	public function list_pools(Page $page, /*array*/ $pools, /*int*/ $pageNumber, /*int*/ $totalPages) { | 	public function list_pools(Page $page, /*array*/ $pools, /*int*/ $pageNumber, /*int*/ $totalPages) { | ||||||
| 		global $user; | 		global $user; | ||||||
| @ -58,12 +87,6 @@ class PoolsTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 		$html .= "</tbody></table>"; | 		$html .= "</tbody></table>"; | ||||||
| 
 | 
 | ||||||
| 		$nav_html = ' |  | ||||||
| 			<a href="'.make_link().'">Index</a> |  | ||||||
| 			<br><a href="'.make_link("pool/new").'">Create Pool</a> |  | ||||||
| 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> |  | ||||||
| 		'; |  | ||||||
| 
 |  | ||||||
| 		$order_html = ' | 		$order_html = ' | ||||||
| 			<select id="order_pool"> | 			<select id="order_pool"> | ||||||
| 			  <option value="created">Recently created</option> | 			  <option value="created">Recently created</option> | ||||||
| @ -73,17 +96,16 @@ class PoolsTheme extends Themelet { | |||||||
| 			</select> | 			</select> | ||||||
| 		'; | 		'; | ||||||
| 
 | 
 | ||||||
| 		$blockTitle = "Pools"; | 		$this->display_top(null, "Pools"); | ||||||
| 		$page->set_title(html_escape($blockTitle)); |  | ||||||
| 		$page->set_heading(html_escape($blockTitle)); |  | ||||||
| 		$page->add_block(new Block($blockTitle, $html, "main", 10)); |  | ||||||
| 		$page->add_block(new Block("Navigation", $nav_html, "left", 10)); |  | ||||||
| 		$page->add_block(new Block("Order By", $order_html, "left", 15)); | 		$page->add_block(new Block("Order By", $order_html, "left", 15)); | ||||||
| 
 | 
 | ||||||
|  | 		$page->add_block(new Block("Pools", $html, "main", 10)); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 		$this->display_paginator($page, "pool/list", null, $pageNumber, $totalPages); | 		$this->display_paginator($page, "pool/list", null, $pageNumber, $totalPages); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	/* | 	/* | ||||||
| 	 * HERE WE DISPLAY THE NEW POOL COMPOSER | 	 * HERE WE DISPLAY THE NEW POOL COMPOSER | ||||||
| 	 */ | 	 */ | ||||||
| @ -99,18 +121,31 @@ class PoolsTheme extends Themelet { | |||||||
| 			</form> | 			</form> | ||||||
| 		";
 | 		";
 | ||||||
| 
 | 
 | ||||||
| 		$blockTitle = "Create Pool"; | 		$this->display_top(null, "Create Pool"); | ||||||
| 		$page->set_title(html_escape($blockTitle)); |  | ||||||
| 		$page->set_heading(html_escape($blockTitle)); |  | ||||||
| 		$page->add_block(new Block("Create Pool", $create_html, "main", 20)); | 		$page->add_block(new Block("Create Pool", $create_html, "main", 20)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
|  | 	 * @param array $pools | ||||||
|  | 	 * @param string $heading | ||||||
|  | 	 * @param bool $check_all | ||||||
|  | 	 */ | ||||||
| 	private function display_top(/*array*/ $pools, /*string*/ $heading, $check_all=false) { | 	private function display_top(/*array*/ $pools, /*string*/ $heading, $check_all=false) { | ||||||
| 		global $page, $user; | 		global $page, $user; | ||||||
| 
 | 
 | ||||||
| 		$page->set_title($heading); | 		$page->set_title($heading); | ||||||
| 		$page->set_heading($heading); | 		$page->set_heading($heading); | ||||||
|  | 
 | ||||||
|  | 		$nav_html = '<a href="'.make_link().'">Index</a>'; | ||||||
|  | 		$poolnav_html = ' | ||||||
|  | 			<a href="'.make_link("pool/list").'">Pool Index</a> | ||||||
|  | 			<br><a href="'.make_link("pool/new").'">Create Pool</a> | ||||||
|  | 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> | ||||||
|  | 		'; | ||||||
|  | 
 | ||||||
|  | 		$page->add_block(new Block($nav_html, null, "left", 5)); | ||||||
|  | 		$page->add_block(new Block("Pool Navigation", $poolnav_html, "left", 10)); | ||||||
|  | 
 | ||||||
| 		if(count($pools) == 1) { | 		if(count($pools) == 1) { | ||||||
| 			$pool = $pools[0]; | 			$pool = $pools[0]; | ||||||
| 			if($pool['public'] == "Y" || $user->is_admin()) {// IF THE POOL IS PUBLIC OR IS ADMIN SHOW EDIT PANEL
 | 			if($pool['public'] == "Y" || $user->is_admin()) {// IF THE POOL IS PUBLIC OR IS ADMIN SHOW EDIT PANEL
 | ||||||
| @ -122,36 +157,15 @@ class PoolsTheme extends Themelet { | |||||||
| 			$bb = new BBCode(); | 			$bb = new BBCode(); | ||||||
| 			$page->add_block(new Block(html_escape($pool['title']), $bb->format($pool['description']), "main", 10)); | 			$page->add_block(new Block(html_escape($pool['title']), $bb->format($pool['description']), "main", 10)); | ||||||
| 		} | 		} | ||||||
| 		else { |  | ||||||
| 			$pool_info = ' |  | ||||||
| 						<table id="poolsList" class="zebra"> |  | ||||||
| 							<thead><tr> |  | ||||||
| 								<th class="left">Title</th> |  | ||||||
| 								<th class="left">Description</th> |  | ||||||
| 							</tr></thead><tbody>'; |  | ||||||
| 
 |  | ||||||
| 			foreach($pools as $pool) { |  | ||||||
| 				$pool_info .= "<tr>". |  | ||||||
| 					"<td class='left'>".html_escape($pool['title'])."</td>". |  | ||||||
| 					"<td class='left'>".html_escape($pool['description'])."</td>". |  | ||||||
| 					"</tr>"; |  | ||||||
| 
 |  | ||||||
| 				// this will make disasters if more than one pool comes in the parameter
 |  | ||||||
| 				if($pool['public'] == "Y" || $user->is_admin()) {// IF THE POOL IS PUBLIC OR IS ADMIN SHOW EDIT PANEL
 |  | ||||||
| 					if(!$user->is_anonymous()) {// IF THE USER IS REGISTERED AND LOGGED IN SHOW EDIT PANEL
 |  | ||||||
| 						$this->sidebar_options($page, $pool, $check_all); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 			$pool_info .= "</tbody></table>"; | 	/** | ||||||
| 			$page->add_block(new Block($heading, $pool_info, "main", 10)); | 	 * HERE WE DISPLAY THE POOL WITH TITLE DESCRIPTION AND IMAGES WITH PAGINATION. | ||||||
| 		} | 	 * | ||||||
| 	} | 	 * @param array $pools | ||||||
| 
 | 	 * @param array $images | ||||||
| 
 | 	 * @param int $pageNumber | ||||||
| 	/* | 	 * @param int $totalPages | ||||||
| 	 * HERE WE DISPLAY THE POOL WITH TITLE DESCRIPTION AND IMAGES WITH PAGINATION |  | ||||||
| 	 */ | 	 */ | ||||||
| 	public function view_pool(/*array*/ $pools, /*array*/ $images, /*int*/ $pageNumber, /*int*/ $totalPages) { | 	public function view_pool(/*array*/ $pools, /*array*/ $images, /*int*/ $pageNumber, /*int*/ $totalPages) { | ||||||
| 		global $user, $page; | 		global $user, $page; | ||||||
| @ -164,20 +178,17 @@ class PoolsTheme extends Themelet { | |||||||
| 			$pool_images .= "\n".$thumb_html."\n"; | 			$pool_images .= "\n".$thumb_html."\n"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$nav_html = ' |  | ||||||
| 			<a href="'.make_link().'">Index</a> |  | ||||||
| 			<br><a href="'.make_link("pool/new").'">Create Pool</a> |  | ||||||
| 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> |  | ||||||
| 		'; |  | ||||||
| 
 |  | ||||||
| 		$page->add_block(new Block("Navigation", $nav_html, "left", 10)); |  | ||||||
| 		$page->add_block(new Block("Viewing Posts", $pool_images, "main", 30)); | 		$page->add_block(new Block("Viewing Posts", $pool_images, "main", 30)); | ||||||
| 		$this->display_paginator($page, "pool/view/".$pools[0]['id'], null, $pageNumber, $totalPages); | 		$this->display_paginator($page, "pool/view/".$pools[0]['id'], null, $pageNumber, $totalPages); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE DISPLAY THE POOL OPTIONS ON SIDEBAR BUT WE HIDE REMOVE OPTION IF THE USER IS NOT THE OWNER OR ADMIN | 	 * HERE WE DISPLAY THE POOL OPTIONS ON SIDEBAR BUT WE HIDE REMOVE OPTION IF THE USER IS NOT THE OWNER OR ADMIN. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $pool | ||||||
|  | 	 * @param bool $check_all | ||||||
| 	 */ | 	 */ | ||||||
| 	public function sidebar_options(Page $page, $pool, /*bool*/ $check_all) { | 	public function sidebar_options(Page $page, $pool, /*bool*/ $check_all) { | ||||||
| 		global $user; | 		global $user; | ||||||
| @ -223,12 +234,7 @@ class PoolsTheme extends Themelet { | |||||||
| 				<script language='javascript' type='text/javascript'> | 				<script language='javascript' type='text/javascript'> | ||||||
| 				<!-- | 				<!-- | ||||||
| 				function setAll(value) { | 				function setAll(value) { | ||||||
| 					var a=new Array(); | 					$('[name=\"check[]\"]').attr('checked', value); | ||||||
| 					a=document.getElementsByName('check[]'); |  | ||||||
| 					var p=0; |  | ||||||
| 					for(i=0;i<a.length;i++){ |  | ||||||
| 						a[i].checked = value; |  | ||||||
| 					} |  | ||||||
| 				} | 				} | ||||||
| 				//-->
 | 				//-->
 | ||||||
| 				</script> | 				</script> | ||||||
| @ -236,27 +242,23 @@ class PoolsTheme extends Themelet { | |||||||
| 				<input type='button' name='UnCheckAll' value='Uncheck All' onClick='setAll(false)'> | 				<input type='button' name='UnCheckAll' value='Uncheck All' onClick='setAll(false)'> | ||||||
| 			";
 | 			";
 | ||||||
| 		} | 		} | ||||||
| 		$page->add_block(new Block("Manage Pool", $editor, "left", 10)); | 		$page->add_block(new Block("Manage Pool", $editor, "left", 15)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE DISPLAY THE RESULT OF THE SEARCH ON IMPORT | 	 * HERE WE DISPLAY THE RESULT OF THE SEARCH ON IMPORT. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $images | ||||||
|  | 	 * @param array $pool | ||||||
| 	 */ | 	 */ | ||||||
| 	public function pool_result(Page $page, /*array*/ $images, /*int*/ $pool_id) { | 	public function pool_result(Page $page, /*array*/ $images, /*array*/ $pool) { | ||||||
| 		// TODO: this could / should be done using jQuery
 | 
 | ||||||
|  | 		$this->display_top($pool, "Importing Posts", true); | ||||||
| 		$pool_images = " | 		$pool_images = " | ||||||
| 			<script language='javascript' type='text/javascript'> | 			<script language='javascript' type='text/javascript'> | ||||||
| 			<!-- | 			<!-- | ||||||
| 			function setAll(value) { |  | ||||||
| 				var a=new Array(); |  | ||||||
| 				a=document.getElementsByName('check[]'); |  | ||||||
| 				var p=0; |  | ||||||
| 				for(i=0;i<a.length;i++) { |  | ||||||
| 					a[i].checked = value; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			function confirm_action() { | 			function confirm_action() { | ||||||
| 				return confirm('Are you sure you want to add selected posts to this pool?'); | 				return confirm('Are you sure you want to add selected posts to this pool?'); | ||||||
| 			} | 			} | ||||||
| @ -273,25 +275,23 @@ class PoolsTheme extends Themelet { | |||||||
| 				'<input name="check[]" type="checkbox" value="'.$image->id.'" />'. | 				'<input name="check[]" type="checkbox" value="'.$image->id.'" />'. | ||||||
| 				'</span>'; | 				'</span>'; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		$pool_images .= "<br>". | 		$pool_images .= "<br>". | ||||||
| 			"<input type='submit' name='edit' id='edit_pool_add_btn' value='Add Selected' onclick='return confirm_action()'/>". | 			"<input type='submit' name='edit' id='edit_pool_add_btn' value='Add Selected' onclick='return confirm_action()'/>". | ||||||
| 			"<input type='hidden' name='pool_id' value='".$pool_id."'>". | 			"<input type='hidden' name='pool_id' value='".$pool[0]['id']."'>". | ||||||
| 			"</form>"; | 			"</form>"; | ||||||
| 
 | 
 | ||||||
| 		$page->add_block(new Block("Import", $pool_images, "main", 10)); | 		$page->add_block(new Block("Import", $pool_images, "main", 30)); | ||||||
| 
 |  | ||||||
| 		$editor = " |  | ||||||
| 			<input type='button' name='CheckAll' value='Check All' onClick='setAll(true)'> |  | ||||||
| 			<input type='button' name='UnCheckAll' value='Uncheck All' onClick='setAll(false)'> |  | ||||||
| 			";
 |  | ||||||
| 
 |  | ||||||
| 		$page->add_block(new Block("Manage Pool", $editor, "left", 10)); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE DISPLAY THE POOL ORDERER | 	 * HERE WE DISPLAY THE POOL ORDERER. | ||||||
| 	 * WE LIST ALL IMAGES ON POOL WITHOUT PAGINATION AND WITH A TEXT INPUT TO SET A NUMBER AND CHANGE THE ORDER | 	 * WE LIST ALL IMAGES ON POOL WITHOUT PAGINATION AND WITH A TEXT INPUT TO SET A NUMBER AND CHANGE THE ORDER | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $pools | ||||||
|  | 	 * @param array $images | ||||||
| 	 */ | 	 */ | ||||||
| 	public function edit_order(Page $page, /*array*/ $pools, /*array*/ $images) { | 	public function edit_order(Page $page, /*array*/ $pools, /*array*/ $images) { | ||||||
| 		global $user; | 		global $user; | ||||||
| @ -318,16 +318,19 @@ class PoolsTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Sorting Posts", $pool_images, "main", 30)); | 		$page->add_block(new Block("Sorting Posts", $pool_images, "main", 30)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	/** | ||||||
| 	/* | 	 * HERE WE DISPLAY THE POOL EDITOR. | ||||||
| 	 * HERE WE DISPLAY THE POOL EDITOR | 	 * | ||||||
| 	 * WE LIST ALL IMAGES ON POOL WITHOUT PAGINATION AND WITH | 	 * WE LIST ALL IMAGES ON POOL WITHOUT PAGINATION AND WITH | ||||||
| 	 * A CHECKBOX TO SELECT WHICH IMAGE WE WANT TO REMOVE | 	 * A CHECKBOX TO SELECT WHICH IMAGE WE WANT TO REMOVE | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $pools | ||||||
|  | 	 * @param array $images | ||||||
| 	 */ | 	 */ | ||||||
| 	public function edit_pool(Page $page, /*array*/ $pools, /*array*/ $images) { | 	public function edit_pool(Page $page, /*array*/ $pools, /*array*/ $images) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		/* EDIT POOL DESCRIPTION */ | 		/* EDIT POOL DESCRIPTION */ | ||||||
| 		$desc_html = " | 		$desc_html = " | ||||||
| 			".make_form(make_link("pool/edit_description"))." | 			".make_form(make_link("pool/edit_description"))." | ||||||
| @ -362,8 +365,12 @@ class PoolsTheme extends Themelet { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * HERE WE DISPLAY THE HISTORY LIST | 	 * HERE WE DISPLAY THE HISTORY LIST. | ||||||
|  | 	 * | ||||||
|  | 	 * @param array $histories | ||||||
|  | 	 * @param int $pageNumber | ||||||
|  | 	 * @param int $totalPages | ||||||
| 	 */ | 	 */ | ||||||
| 	public function show_history($histories, /*int*/ $pageNumber, /*int*/ $totalPages) { | 	public function show_history($histories, /*int*/ $pageNumber, /*int*/ $totalPages) { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -409,15 +416,7 @@ class PoolsTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 		$html .= "</tbody></table>"; | 		$html .= "</tbody></table>"; | ||||||
| 
 | 
 | ||||||
| 		$nav_html = ' | 		$this->display_top(null, "Recent Changes"); | ||||||
| 			<a href="'.make_link().'">Index</a> |  | ||||||
| 			<br><a href="'.make_link("pool/new").'">Create Pool</a> |  | ||||||
| 			<br><a href="'.make_link("pool/updated").'">Pool Changes</a> |  | ||||||
| 		'; |  | ||||||
| 
 |  | ||||||
| 		$page->set_title("Recent Changes"); |  | ||||||
| 		$page->set_heading("Recent Changes"); |  | ||||||
| 		$page->add_block(new Block("Navigation", $nav_html, "left", 10)); |  | ||||||
| 		$page->add_block(new Block("Recent Changes", $html, "main", 10)); | 		$page->add_block(new Block("Recent Changes", $html, "main", 10)); | ||||||
| 
 | 
 | ||||||
| 		$this->display_paginator($page, "pool/updated", null, $pageNumber, $totalPages); | 		$this->display_paginator($page, "pool/updated", null, $pageNumber, $totalPages); | ||||||
|  | |||||||
| @ -1,9 +1,12 @@ | |||||||
| <?php | <?php | ||||||
| class QRImageTheme extends Themelet { | class QRImageTheme extends Themelet { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $link | ||||||
|  | 	 */ | ||||||
| 	public function links_block($link) { | 	public function links_block($link) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 		$page->add_block( new Block( | 		$page->add_block( new Block( | ||||||
| 			"QR Code","<img alt='QR Code' src='http://chart.apis.google.com/chart?chs=150x150&cht=qr&chl=$link' />","left",50)); | 			"QR Code","<img alt='QR Code' src='http://chart.apis.google.com/chart?chs=150x150&cht=qr&chl={$link}' />","left",50)); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -22,7 +22,8 @@ | |||||||
| 
 | 
 | ||||||
| class RandomImage extends Extension { | class RandomImage extends Extension { | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		global $config, $database, $page, $user; | 		global $page; | ||||||
|  | 
 | ||||||
| 		if($event->page_matches("random_image")) { | 		if($event->page_matches("random_image")) { | ||||||
| 			$action = ''; | 			$action = ''; | ||||||
| 			if($event->count_args() == 1) { | 			if($event->count_args() == 1) { | ||||||
| @ -34,7 +35,7 @@ class RandomImage extends Extension { | |||||||
| 				$search_terms = explode(' ', $event->get_arg(1)); | 				$search_terms = explode(' ', $event->get_arg(1)); | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
| 				# FIXME: throw exception
 | 				throw new SCoreException("Error: too many arguments."); | ||||||
| 			} | 			} | ||||||
| 			$image = Image::by_random($search_terms); | 			$image = Image::by_random($search_terms); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,24 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class RandomImageTheme extends Themelet { | class RandomImageTheme extends Themelet | ||||||
| 	public function display_random(Page $page, Image $image) { | { | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 */ | ||||||
|  | 	public function display_random(Page $page, Image $image) | ||||||
|  | 	{ | ||||||
| 		$page->add_block(new Block("Random Image", $this->build_random_html($image), "left", 8)); | 		$page->add_block(new Block("Random Image", $this->build_random_html($image), "left", 8)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		public function build_random_html(Image $image, $query=null) { | 	/** | ||||||
| 		global $config; | 	 * @param Image $image | ||||||
|  | 	 * @param null|string $query | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
|  | 	public function build_random_html(Image $image, $query = null) | ||||||
|  | 	{ | ||||||
|  | 
 | ||||||
| 		$i_id = int_escape($image->id); | 		$i_id = int_escape($image->id); | ||||||
| 		$h_view_link = make_link("post/view/$i_id", $query); | 		$h_view_link = make_link("post/view/$i_id", $query); | ||||||
| 		$h_thumb_link = $image->get_thumb_link(); | 		$h_thumb_link = $image->get_thumb_link(); | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| <?php | <?php | ||||||
| /* needed for access to build_thumb_html */ | /* needed for access to build_thumb_html */ | ||||||
| class RandomListTheme extends Themelet {} | class RandomListTheme extends Themelet {} | ||||||
| ?>
 | 
 | ||||||
|  | |||||||
| @ -20,10 +20,18 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class RatingSetEvent extends Event { | class RatingSetEvent extends Event { | ||||||
| 	var $image, $rating; | 	/** @var \Image */ | ||||||
|  | 	public $image; | ||||||
|  | 	/** @var string  */ | ||||||
|  | 	public $rating; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param string $rating | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Image $image, /*char*/ $rating) { | 	public function __construct(Image $image, /*char*/ $rating) { | ||||||
| 		assert(in_array($rating, array("s", "q", "e", "u"))); | 		assert(in_array($rating, array("s", "q", "e", "u"))); | ||||||
|  | 
 | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| 		$this->rating = $rating; | 		$this->rating = $rating; | ||||||
| 	} | 	} | ||||||
| @ -31,6 +39,9 @@ class RatingSetEvent extends Event { | |||||||
| 
 | 
 | ||||||
| class Ratings extends Extension { | class Ratings extends Extension { | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	public function get_priority() {return 50;} | 	public function get_priority() {return 50;} | ||||||
| 
 | 
 | ||||||
| 	public function onInitExt(InitExtEvent $event) { | 	public function onInitExt(InitExtEvent $event) { | ||||||
| @ -69,7 +80,7 @@ class Ratings extends Extension { | |||||||
| 
 | 
 | ||||||
| 	 | 	 | ||||||
| 	public function onDisplayingImage(DisplayingImageEvent $event) { | 	public function onDisplayingImage(DisplayingImageEvent $event) { | ||||||
| 		global $user, $database, $page; | 		global $user, $page; | ||||||
| 		/** | 		/** | ||||||
| 		 * Deny images upon insufficient permissions. | 		 * Deny images upon insufficient permissions. | ||||||
| 		 **/ | 		 **/ | ||||||
| @ -97,15 +108,13 @@ class Ratings extends Extension { | |||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public function onImageInfoSet(ImageInfoSetEvent $event) { | 	public function onImageInfoSet(ImageInfoSetEvent $event) { | ||||||
| 		global $user; |  | ||||||
| 		 |  | ||||||
| 		if($this->can_rate() && isset($_POST["rating"])) { | 		if($this->can_rate() && isset($_POST["rating"])) { | ||||||
| 			send_event(new RatingSetEvent($event->image, $_POST['rating'])); | 			send_event(new RatingSetEvent($event->image, $_POST['rating'])); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onParseLinkTemplate(ParseLinkTemplateEvent $event) { | 	public function onParseLinkTemplate(ParseLinkTemplateEvent $event) { | ||||||
| 		$event->replace('$rating', $this->theme->rating_to_name($event->image->rating)); | 		$event->replace('$rating', $this->rating_to_human($event->image->rating)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onSearchTermParse(SearchTermParseEvent $event) { | 	public function onSearchTermParse(SearchTermParseEvent $event) { | ||||||
| @ -125,11 +134,11 @@ class Ratings extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		global $database, $user, $page; | 		global $user, $page; | ||||||
| 		 | 		 | ||||||
| 		if ($event->page_matches("admin/bulk_rate")) { | 		if ($event->page_matches("admin/bulk_rate")) { | ||||||
| 			if(!$user->is_admin()) { | 			if(!$user->is_admin()) { | ||||||
| 				throw PermissionDeniedException(); | 				throw new PermissionDeniedException(); | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
| 				$n = 0; | 				$n = 0; | ||||||
| @ -155,8 +164,13 @@ class Ratings extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static function get_user_privs($user) { | 	/** | ||||||
|  | 	 * @param \User $user | ||||||
|  | 	 * @return null|string | ||||||
|  | 	 */ | ||||||
|  | 	public static function get_user_privs(User $user) { | ||||||
| 		global $config; | 		global $config; | ||||||
|  | 
 | ||||||
| 		if($user->is_anonymous()) { | 		if($user->is_anonymous()) { | ||||||
| 			$sqes = $config->get_string("ext_rating_anon_privs"); | 			$sqes = $config->get_string("ext_rating_anon_privs"); | ||||||
| 		} | 		} | ||||||
| @ -169,6 +183,10 @@ class Ratings extends Extension { | |||||||
| 		return $sqes; | 		return $sqes; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $sqes | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public static function privs_to_sql(/*string*/ $sqes) { | 	public static function privs_to_sql(/*string*/ $sqes) { | ||||||
| 		$arr = array(); | 		$arr = array(); | ||||||
| 		$length = strlen($sqes); | 		$length = strlen($sqes); | ||||||
| @ -179,6 +197,10 @@ class Ratings extends Extension { | |||||||
| 		return $set; | 		return $set; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $rating | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public static function rating_to_human(/*string*/ $rating) { | 	public static function rating_to_human(/*string*/ $rating) { | ||||||
| 		switch($rating) { | 		switch($rating) { | ||||||
| 			case "s": return "Safe"; | 			case "s": return "Safe"; | ||||||
| @ -188,7 +210,11 @@ class Ratings extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// FIXME: this is a bit ugly and guessey, should have proper options
 | 	/** | ||||||
|  | 	 * FIXME: this is a bit ugly and guessey, should have proper options | ||||||
|  | 	 * | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function can_rate() { | 	private function can_rate() { | ||||||
| 		global $config, $user; | 		global $config, $user; | ||||||
| 		if($user->is_anonymous() && $config->get_string("ext_rating_anon_privs") == "sqeu") return false; | 		if($user->is_anonymous() && $config->get_string("ext_rating_anon_privs") == "sqeu") return false; | ||||||
| @ -197,6 +223,10 @@ class Ratings extends Extension { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param $context | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function no_rating_query($context) { | 	private function no_rating_query($context) { | ||||||
| 		foreach($context as $term) { | 		foreach($context as $term) { | ||||||
| 			if(preg_match("/^rating[=|:]/", $term)) { | 			if(preg_match("/^rating[=|:]/", $term)) { | ||||||
| @ -207,8 +237,7 @@ class Ratings extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private function install() { | 	private function install() { | ||||||
| 		global $database; | 		global $database, $config; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		if($config->get_int("ext_ratings2_version") < 1) { | 		if($config->get_int("ext_ratings2_version") < 1) { | ||||||
| 			$database->Execute("ALTER TABLE images ADD COLUMN rating CHAR(1) NOT NULL DEFAULT 'u'"); | 			$database->Execute("ALTER TABLE images ADD COLUMN rating CHAR(1) NOT NULL DEFAULT 'u'"); | ||||||
| @ -227,11 +256,16 @@ class Ratings extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param string $rating | ||||||
|  | 	 * @param string $old_rating | ||||||
|  | 	 */ | ||||||
| 	private function set_rating(/*int*/ $image_id, /*string*/ $rating, /*string*/ $old_rating) { | 	private function set_rating(/*int*/ $image_id, /*string*/ $rating, /*string*/ $old_rating) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		if($old_rating != $rating){ | 		if($old_rating != $rating){ | ||||||
| 			$database->Execute("UPDATE images SET rating=? WHERE id=?", array($rating, $image_id)); | 			$database->Execute("UPDATE images SET rating=? WHERE id=?", array($rating, $image_id)); | ||||||
| 			log_info("rating", "Rating for Image #{$image_id} set to: ".$this->theme->rating_to_name($rating)); | 			log_info("rating", "Rating for Image #{$image_id} set to: ".$this->rating_to_human($rating)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,11 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class RatingsTheme extends Themelet { | class RatingsTheme extends Themelet { | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param string $rating | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	public function get_rater_html(/*int*/ $image_id, /*string*/ $rating) { | 	public function get_rater_html(/*int*/ $image_id, /*string*/ $rating) { | ||||||
| 		$s_checked = $rating == 's' ? " checked" : ""; | 		$s_checked = $rating == 's' ? " checked" : ""; | ||||||
| 		$q_checked = $rating == 'q' ? " checked" : ""; | 		$q_checked = $rating == 'q' ? " checked" : ""; | ||||||
| @ -34,15 +39,6 @@ class RatingsTheme extends Themelet { | |||||||
| 		";
 | 		";
 | ||||||
| 		$page->add_block(new Block("List Controls", $html, "left")); | 		$page->add_block(new Block("List Controls", $html, "left")); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	public function rating_to_name(/*string*/ $rating) { |  | ||||||
| 		switch($rating) { |  | ||||||
| 			case 's': return "Safe"; |  | ||||||
| 			case 'q': return "Questionable"; |  | ||||||
| 			case 'e': return "Explicit"; |  | ||||||
| 			default: return "Unknown"; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -15,7 +15,7 @@ | |||||||
| 
 | 
 | ||||||
| class RegenThumb extends Extension { | class RegenThumb extends Extension { | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		global $config, $database, $page, $user; | 		global $page, $user; | ||||||
| 
 | 
 | ||||||
| 		if($event->page_matches("regen_thumb") && $user->can("delete_image") && isset($_POST['image_id'])) { | 		if($event->page_matches("regen_thumb") && $user->can("delete_image") && isset($_POST['image_id'])) { | ||||||
| 			$image = Image::by_id(int_escape($_POST['image_id'])); | 			$image = Image::by_id(int_escape($_POST['image_id'])); | ||||||
|  | |||||||
| @ -1,8 +1,11 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class RegenThumbTheme extends Themelet { | class RegenThumbTheme extends Themelet { | ||||||
| 	/* | 	/** | ||||||
| 	 * Show a form which offers to regenerate the thumb of an image with ID #$image_id
 | 	 * Show a form which offers to regenerate the thumb of an image with ID #$image_id
 | ||||||
|  | 	 * | ||||||
|  | 	 * @param int|string $image_id | ||||||
|  | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_buttons_html($image_id) { | 	public function get_buttons_html($image_id) { | ||||||
| 		return " | 		return " | ||||||
| @ -13,8 +16,11 @@ class RegenThumbTheme extends Themelet { | |||||||
| 		";
 | 		";
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * Show a link to the new thumbnail | 	 * Show a link to the new thumbnail. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param Image $image | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_results(Page $page, Image $image) { | 	public function display_results(Page $page, Image $image) { | ||||||
| 		$page->set_title("Thumbnail Regenerated"); | 		$page->set_title("Thumbnail Regenerated"); | ||||||
|  | |||||||
| @ -21,7 +21,6 @@ class Relationships extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onImageInfoSet(ImageInfoSetEvent $event) { | 	public function onImageInfoSet(ImageInfoSetEvent $event) { | ||||||
|         global $user; |  | ||||||
| 		if(isset($_POST['tag_edit__tags']) ? !preg_match('/parent[=|:]/', $_POST["tag_edit__tags"]) : TRUE) { //Ignore tag_edit__parent if tags contain parent metatag
 | 		if(isset($_POST['tag_edit__tags']) ? !preg_match('/parent[=|:]/', $_POST["tag_edit__tags"]) : TRUE) { //Ignore tag_edit__parent if tags contain parent metatag
 | ||||||
| 			if (isset($_POST["tag_edit__parent"]) ? ctype_digit($_POST["tag_edit__parent"]) : FALSE) { | 			if (isset($_POST["tag_edit__parent"]) ? ctype_digit($_POST["tag_edit__parent"]) : FALSE) { | ||||||
| 				$this->set_parent($event->image->id, (int) $_POST["tag_edit__parent"]); | 				$this->set_parent($event->image->id, (int) $_POST["tag_edit__parent"]); | ||||||
| @ -91,6 +90,10 @@ class Relationships extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $imageID | ||||||
|  | 	 * @param int $parentID | ||||||
|  | 	 */ | ||||||
| 	private function set_parent(/*int*/ $imageID, /*int*/ $parentID){ | 	private function set_parent(/*int*/ $imageID, /*int*/ $parentID){ | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| @ -100,6 +103,10 @@ class Relationships extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $parentID | ||||||
|  | 	 * @param int $childID | ||||||
|  | 	 */ | ||||||
| 	private function set_child(/*int*/ $parentID, /*int*/ $childID){ | 	private function set_child(/*int*/ $parentID, /*int*/ $childID){ | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| @ -109,6 +116,9 @@ class Relationships extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $imageID | ||||||
|  | 	 */ | ||||||
| 	private function remove_parent(/*int*/ $imageID){ | 	private function remove_parent(/*int*/ $imageID){ | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$parentID = $database->get_one("SELECT parent_id FROM images WHERE id = :iid", array("iid"=>$imageID)); | 		$parentID = $database->get_one("SELECT parent_id FROM images WHERE id = :iid", array("iid"=>$imageID)); | ||||||
|  | |||||||
| @ -1,6 +1,9 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class RelationshipsTheme extends Themelet { | class RelationshipsTheme extends Themelet { | ||||||
|  | 	/** | ||||||
|  | 	 * @param \Image $image | ||||||
|  | 	 */ | ||||||
| 	public function relationship_info($image) { | 	public function relationship_info($image) { | ||||||
| 		global $page, $database; | 		global $page, $database; | ||||||
| 
 | 
 | ||||||
| @ -25,6 +28,7 @@ class RelationshipsTheme extends Themelet { | |||||||
| 
 | 
 | ||||||
| 	public function get_parent_editor_html(Image $image) { | 	public function get_parent_editor_html(Image $image) { | ||||||
| 		global $user; | 		global $user; | ||||||
|  | 
 | ||||||
| 		$h_parent_id = $image->parent_id; | 		$h_parent_id = $image->parent_id; | ||||||
| 		$s_parent_id = $h_parent_id ?: "None."; | 		$s_parent_id = $h_parent_id ?: "None."; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,18 +10,30 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class RemoveReportedImageEvent extends Event { | class RemoveReportedImageEvent extends Event { | ||||||
| 	var $id; | 	/** @var  int */ | ||||||
|  | 	public $id; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $id | ||||||
|  | 	 */ | ||||||
| 	public function __construct($id) { | 	public function __construct($id) { | ||||||
| 		$this->id = $id; | 		$this->id = $id; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class AddReportedImageEvent extends Event { | class AddReportedImageEvent extends Event { | ||||||
| 	var $reporter_id; | 	/** @var int  */ | ||||||
| 	var $image_id; | 	public $reporter_id; | ||||||
| 	var $reason; | 	/** @var int  */ | ||||||
|  | 	public $image_id; | ||||||
|  | 	/** @var string  */ | ||||||
|  | 	public $reason; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param int $reporter_id | ||||||
|  | 	 * @param string $reason | ||||||
|  | 	 */ | ||||||
| 	public function __construct($image_id, $reporter_id, $reason) { | 	public function __construct($image_id, $reporter_id, $reason) { | ||||||
| 		$this->reporter_id = $reporter_id; | 		$this->reporter_id = $reporter_id; | ||||||
| 		$this->image_id = $image_id; | 		$this->image_id = $image_id; | ||||||
| @ -89,7 +101,7 @@ class ReportImage extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onDisplayingImage(DisplayingImageEvent $event) { | 	public function onDisplayingImage(DisplayingImageEvent $event) { | ||||||
| 		global $config, $user, $page; | 		global $user, $page; | ||||||
| 		if($user->can('create_image_report')) { | 		if($user->can('create_image_report')) { | ||||||
| 			$reps = $this->get_reporters($event->image); | 			$reps = $this->get_reporters($event->image); | ||||||
| 			$this->theme->display_image_banner($event->image, $reps); | 			$this->theme->display_image_banner($event->image, $reps); | ||||||
| @ -112,8 +124,8 @@ class ReportImage extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	protected function install() { | 	protected function install() { | ||||||
| 		global $database; | 		global $database, $config; | ||||||
| 		global $config; | 
 | ||||||
| 		if($config->get_int("ext_report_image_version") < 1) { | 		if($config->get_int("ext_report_image_version") < 1) { | ||||||
| 			$database->create_table("image_reports", " | 			$database->create_table("image_reports", " | ||||||
| 				id SCORE_AIPK, | 				id SCORE_AIPK, | ||||||
| @ -127,8 +139,13 @@ class ReportImage extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_reporters(Image $image) { | 	public function get_reporters(Image $image) { | ||||||
| 		global $database; | 		global $database; | ||||||
|  | 
 | ||||||
| 		return $database->get_col(" | 		return $database->get_col(" | ||||||
| 			SELECT users.name | 			SELECT users.name | ||||||
| 			FROM image_reports | 			FROM image_reports | ||||||
| @ -137,8 +154,12 @@ class ReportImage extends Extension { | |||||||
| 		", array("image_id" => $image->id));
 | 		", array("image_id" => $image->id));
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_reported_images() { | 	public function get_reported_images() { | ||||||
| 		global $config, $database; | 		global $database; | ||||||
|  | 
 | ||||||
| 		$all_reports = $database->get_all(" | 		$all_reports = $database->get_all(" | ||||||
| 			SELECT image_reports.*, users.name AS reporter_name | 			SELECT image_reports.*, users.name AS reporter_name | ||||||
| 			FROM image_reports | 			FROM image_reports | ||||||
| @ -160,6 +181,9 @@ class ReportImage extends Extension { | |||||||
| 		return $reports; | 		return $reports; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return mixed | ||||||
|  | 	 */ | ||||||
| 	public function count_reported_images() { | 	public function count_reported_images() { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -11,6 +11,10 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class ReportImageTheme extends Themelet { | class ReportImageTheme extends Themelet { | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $reports | ||||||
|  | 	 */ | ||||||
| 	public function display_reported_images(Page $page, $reports) { | 	public function display_reported_images(Page $page, $reports) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 
 | 
 | ||||||
| @ -57,11 +61,14 @@ class ReportImageTheme extends Themelet { | |||||||
| 		$page->set_heading("Reported Images"); | 		$page->set_heading("Reported Images"); | ||||||
| 		$page->add_block(new NavBlock()); | 		$page->add_block(new NavBlock()); | ||||||
| 		$page->add_block(new Block("Reported Images", $html)); | 		$page->add_block(new Block("Reported Images", $html)); | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param array $reporters | ||||||
|  | 	 */ | ||||||
| 	public function display_image_banner(Image $image, /*array*/ $reporters) { | 	public function display_image_banner(Image $image, /*array*/ $reporters) { | ||||||
| 		global $config, $page; | 		global $page; | ||||||
| 
 | 
 | ||||||
| 		$i_image = int_escape($image->id); | 		$i_image = int_escape($image->id); | ||||||
| 		$html = ""; | 		$html = ""; | ||||||
|  | |||||||
| @ -154,9 +154,14 @@ class ResizeImage extends Extension { | |||||||
| 	// Private functions
 | 	// Private functions
 | ||||||
| 	/* ----------------------------- */ | 	/* ----------------------------- */ | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 		This function could be made much smaller by using the ImageReplaceEvent | 	 * This function could be made much smaller by using the ImageReplaceEvent | ||||||
| 		ie: Pretend that we are replacing the image with a resized copy. | 	 * ie: Pretend that we are replacing the image with a resized copy. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Image $image_obj | ||||||
|  | 	 * @param int $width | ||||||
|  | 	 * @param int $height | ||||||
|  | 	 * @throws ImageResizeException | ||||||
| 	 */ | 	 */ | ||||||
| 	private function resize_image(Image $image_obj, /*int*/ $width, /*int*/ $height) { | 	private function resize_image(Image $image_obj, /*int*/ $width, /*int*/ $height) { | ||||||
| 		global $config, $user, $page, $database; | 		global $config, $user, $page, $database; | ||||||
|  | |||||||
| @ -16,8 +16,12 @@ | |||||||
|  * This class is just a wrapper around SCoreException. |  * This class is just a wrapper around SCoreException. | ||||||
|  */ |  */ | ||||||
| class ImageRotateException extends SCoreException { | class ImageRotateException extends SCoreException { | ||||||
| 	var $error; | 	/** @var string */ | ||||||
|  | 	public $error; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $error | ||||||
|  | 	 */ | ||||||
| 	public function __construct($error) { | 	public function __construct($error) { | ||||||
| 		$this->error = $error; | 		$this->error = $error; | ||||||
| 	} | 	} | ||||||
| @ -101,9 +105,13 @@ class RotateImage extends Extension { | |||||||
| 	// Private functions
 | 	// Private functions
 | ||||||
| 	/* ----------------------------- */ | 	/* ----------------------------- */ | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 		This function could be made much smaller by using the ImageReplaceEvent | 	 * This function could be made much smaller by using the ImageReplaceEvent | ||||||
| 		ie: Pretend that we are replacing the image with a rotated copy. | 	 * ie: Pretend that we are replacing the image with a rotated copy. | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param int $deg | ||||||
|  | 	 * @throws ImageRotateException | ||||||
| 	 */ | 	 */ | ||||||
| 	private function rotate_image(/*int*/ $image_id, /*int*/ $deg) { | 	private function rotate_image(/*int*/ $image_id, /*int*/ $deg) { | ||||||
| 		global $config, $user, $page, $database; | 		global $config, $user, $page, $database; | ||||||
|  | |||||||
| @ -1,12 +1,13 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class RotateImageTheme extends Themelet { | class RotateImageTheme extends Themelet { | ||||||
| 	/* | 	/** | ||||||
| 	 * Display a link to rotate an image | 	 * Display a link to rotate an image. | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| 	public function get_rotate_html(/*int*/ $image_id) { | 	public function get_rotate_html(/*int*/ $image_id) { | ||||||
| 		global $user, $config; |  | ||||||
| 
 |  | ||||||
| 		$html = " | 		$html = " | ||||||
| 			".make_form(make_link('rotate/'.$image_id), 'POST')." | 			".make_form(make_link('rotate/'.$image_id), 'POST')." | ||||||
| 				<input type='hidden' name='image_id' value='$image_id'> | 				<input type='hidden' name='image_id' value='$image_id'> | ||||||
| @ -18,6 +19,13 @@ class RotateImageTheme extends Themelet { | |||||||
| 		return $html; | 		return $html; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Display the error. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param string $title | ||||||
|  | 	 * @param string $message | ||||||
|  | 	 */ | ||||||
| 	public function display_rotate_error(Page $page, /*string*/ $title, /*string*/ $message) { | 	public function display_rotate_error(Page $page, /*string*/ $title, /*string*/ $message) { | ||||||
| 		$page->set_title("Rotate Image"); | 		$page->set_title("Rotate Image"); | ||||||
| 		$page->set_heading("Rotate Image"); | 		$page->set_heading("Rotate Image"); | ||||||
|  | |||||||
| @ -33,6 +33,11 @@ class RSS_Images extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $images | ||||||
|  | 	 * @param array $search_terms | ||||||
|  | 	 * @param int $page_number | ||||||
|  | 	 */ | ||||||
| 	private function do_rss($images, $search_terms, /*int*/ $page_number) { | 	private function do_rss($images, $search_terms, /*int*/ $page_number) { | ||||||
| 		global $page; | 		global $page; | ||||||
| 		global $config; | 		global $config; | ||||||
| @ -78,6 +83,10 @@ class RSS_Images extends Extension { | |||||||
| 		$page->set_data($xml); | 		$page->set_data($xml); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function thumb(Image $image) { | 	private function thumb(Image $image) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,8 +12,12 @@ | |||||||
|  * activated; new config options are in $_POST |  * activated; new config options are in $_POST | ||||||
|  */ |  */ | ||||||
| class ConfigSaveEvent extends Event { | class ConfigSaveEvent extends Event { | ||||||
| 	var $config; | 	/** @var \Config */ | ||||||
|  | 	public $config; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Config $config | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Config $config) { | 	public function __construct(Config $config) { | ||||||
| 		$this->config = $config; | 		$this->config = $config; | ||||||
| 	} | 	} | ||||||
| @ -24,8 +28,12 @@ class ConfigSaveEvent extends Event { | |||||||
|  * Sent when the setup page is ready to be added to |  * Sent when the setup page is ready to be added to | ||||||
|  */ |  */ | ||||||
| class SetupBuildingEvent extends Event { | class SetupBuildingEvent extends Event { | ||||||
| 	var $panel; | 	/** @var \SetupPanel */ | ||||||
|  | 	public $panel; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param SetupPanel $panel | ||||||
|  | 	 */ | ||||||
| 	public function __construct(SetupPanel $panel) { | 	public function __construct(SetupPanel $panel) { | ||||||
| 		$this->panel = $panel; | 		$this->panel = $panel; | ||||||
| 	} | 	} | ||||||
| @ -35,8 +43,12 @@ class SetupBuildingEvent extends Event { | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class SetupPanel { | class SetupPanel { | ||||||
| 	var $blocks = array(); | 	/** @var \SetupBlock[]  */ | ||||||
|  | 	public $blocks = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param SetupBlock $block | ||||||
|  | 	 */ | ||||||
| 	public function add_block(SetupBlock $block) { | 	public function add_block(SetupBlock $block) { | ||||||
| 		$this->blocks[] = $block; | 		$this->blocks[] = $block; | ||||||
| 	} | 	} | ||||||
| @ -46,9 +58,14 @@ class SetupPanel { | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class SetupBlock extends Block { | class SetupBlock extends Block { | ||||||
| 	var $header; | 	/** @var string  */ | ||||||
| 	var $body; | 	public $header; | ||||||
|  | 	/** @var string  */ | ||||||
|  | 	public $body; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $title | ||||||
|  | 	 */ | ||||||
| 	public function __construct($title) { | 	public function __construct($title) { | ||||||
| 		$this->header = $title; | 		$this->header = $title; | ||||||
| 		$this->section = "main"; | 		$this->section = "main"; | ||||||
| @ -56,20 +73,31 @@ class SetupBlock extends Block { | |||||||
| 		$this->body = ""; | 		$this->body = ""; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 */ | ||||||
| 	public function add_label($text) { | 	public function add_label($text) { | ||||||
| 		$this->body .= $text; | 		$this->body .= $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $label | ||||||
|  | 	 */ | ||||||
| 	public function add_text_option($name, $label=null) { | 	public function add_text_option($name, $label=null) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$val = html_escape($config->get_string($name)); | 		$val = html_escape($config->get_string($name)); | ||||||
| 		if(!is_null($label)) { | 		if(!is_null($label)) { | ||||||
| 			$this->body .= "<label for='$name'>$label</label>"; | 			$this->body .= "<label for='{$name}'>{$label}</label>"; | ||||||
| 		} | 		} | ||||||
| 		$this->body .= "<input type='text' id='$name' name='_config_$name' value='$val'>\n"; | 		$this->body .= "<input type='text' id='{$name}' name='_config_{$name}' value='{$val}'>\n"; | ||||||
| 		$this->body .= "<input type='hidden' name='_type_$name' value='string'>\n"; | 		$this->body .= "<input type='hidden' name='_type_{$name}' value='string'>\n"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $label | ||||||
|  | 	 */ | ||||||
| 	public function add_longtext_option($name, $label=null) { | 	public function add_longtext_option($name, $label=null) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$val = html_escape($config->get_string($name)); | 		$val = html_escape($config->get_string($name)); | ||||||
| @ -81,6 +109,10 @@ class SetupBlock extends Block { | |||||||
| 		$this->body .= "<input type='hidden' name='_type_$name' value='string'>\n"; | 		$this->body .= "<input type='hidden' name='_type_$name' value='string'>\n"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $label | ||||||
|  | 	 */ | ||||||
| 	public function add_bool_option($name, $label=null) { | 	public function add_bool_option($name, $label=null) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$checked = $config->get_bool($name) ? " checked" : ""; | 		$checked = $config->get_bool($name) ? " checked" : ""; | ||||||
| @ -97,6 +129,10 @@ class SetupBlock extends Block { | |||||||
| //		$this->body .= "<input type='hidden' id='$name' name='$name' value='$val'>";
 | //		$this->body .= "<input type='hidden' id='$name' name='$name' value='$val'>";
 | ||||||
| //	}
 | //	}
 | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $label | ||||||
|  | 	 */ | ||||||
| 	public function add_int_option($name, $label=null) { | 	public function add_int_option($name, $label=null) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$val = html_escape($config->get_string($name)); | 		$val = html_escape($config->get_string($name)); | ||||||
| @ -107,6 +143,10 @@ class SetupBlock extends Block { | |||||||
| 		$this->body .= "<input type='hidden' name='_type_$name' value='int'>\n"; | 		$this->body .= "<input type='hidden' name='_type_$name' value='int'>\n"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param null|string $label | ||||||
|  | 	 */ | ||||||
| 	public function add_shorthand_int_option($name, $label=null) { | 	public function add_shorthand_int_option($name, $label=null) { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		$val = to_shorthand_int($config->get_string($name)); | 		$val = to_shorthand_int($config->get_string($name)); | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ class _SafeImage { | |||||||
| 		$this->posted   = $img->posted_timestamp; | 		$this->posted   = $img->posted_timestamp; | ||||||
| 		$this->source   = $img->source; | 		$this->source   = $img->source; | ||||||
| 		$this->owner_id = $img->owner_id; | 		$this->owner_id = $img->owner_id; | ||||||
| 		$this->tags     = $img->tag_array; | 		$this->tags     = $img->get_tag_array(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ | |||||||
|  * For Shimmie2 specific extensions, there is a ShimmieWebTestCase class which |  * For Shimmie2 specific extensions, there is a ShimmieWebTestCase class which | ||||||
|  * includes functions to upload and delete images. |  * includes functions to upload and delete images. | ||||||
|  * |  * | ||||||
|  * For a quick guide on the spcifics of how to write tests, see \ref wut |  * For a quick guide on the specifics of how to write tests, see \ref wut | ||||||
|  * |  * | ||||||
|  * |  * | ||||||
|  * \page wut Writing Unit Tests |  * \page wut Writing Unit Tests | ||||||
| @ -88,19 +88,24 @@ define('ADMIN_NAME', "demo"); | |||||||
| define('ADMIN_PASS', "demo"); | define('ADMIN_PASS', "demo"); | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A set of common SCore activities to test |  * Class SCoreWebTestCase | ||||||
|  |  * | ||||||
|  |  * A set of common SCore activities to test. | ||||||
|  */ |  */ | ||||||
| class SCoreWebTestCase extends WebTestCase { | class SCoreWebTestCase extends WebTestCase { | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Click on a link or a button | 	 * Click on a link or a button. | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 * @return string | ||||||
| 	 */ | 	 */ | ||||||
| 	public function click($text) { | 	public function click($text) { | ||||||
| 		return parent::click($text); | 		return parent::click($text); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Click the virtual browser's back button | 	 * Click the virtual browser's back button. | ||||||
|  | 	 * @return bool | ||||||
| 	 */ | 	 */ | ||||||
| 	public function back() { | 	public function back() { | ||||||
| 		return parent::back(); | 		return parent::back(); | ||||||
| @ -165,9 +170,16 @@ class SCoreWebTestCase extends WebTestCase { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A set of common Shimmie activities to test |  * Class ShimmieWebTestCase | ||||||
|  |  * | ||||||
|  |  * A set of common Shimmie activities to test. | ||||||
|  */ |  */ | ||||||
| class ShimmieWebTestCase extends SCoreWebTestCase { | class ShimmieWebTestCase extends SCoreWebTestCase { | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $filename | ||||||
|  | 	 * @param string|string[] $tags | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	protected function post_image($filename, $tags) { | 	protected function post_image($filename, $tags) { | ||||||
| 		$image_id = -1; | 		$image_id = -1; | ||||||
| 		$this->setMaximumRedirects(0); | 		$this->setMaximumRedirects(0); | ||||||
| @ -195,6 +207,9 @@ class ShimmieWebTestCase extends SCoreWebTestCase { | |||||||
| 		return $image_id; | 		return $image_id; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 */ | ||||||
| 	protected function delete_image($image_id) { | 	protected function delete_image($image_id) { | ||||||
| 		if($image_id > 0) { | 		if($image_id > 0) { | ||||||
| 	        $this->get_page('post/view/'.$image_id); | 	        $this->get_page('post/view/'.$image_id); | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| <?php | <?php | ||||||
|  | 
 | ||||||
| /* | /* | ||||||
|  * Name: XML Sitemap |  * Name: XML Sitemap | ||||||
|  * Author: Sein Kraft <mail@seinkraft.info> |  * Author: Sein Kraft <mail@seinkraft.info> | ||||||
| @ -9,30 +10,31 @@ | |||||||
|  * Documentation: |  * Documentation: | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| class XMLSitemap extends Extension { | class XMLSitemap extends Extension | ||||||
|  | { | ||||||
| 	private $sitemap_queue = ""; | 	private $sitemap_queue = ""; | ||||||
| 	private $sitemap_filepath = ""; // set onPageRequest
 | 	private $sitemap_filepath = ""; // set onPageRequest
 | ||||||
| 
 | 
 | ||||||
| 	public function onPageRequest(PageRequestEvent $event) {  | 	public function onPageRequest(PageRequestEvent $event) | ||||||
|             if($event->page_matches("sitemap.xml"))  |  | ||||||
| 	{ | 	{ | ||||||
|  | 		if ($event->page_matches("sitemap.xml")) { | ||||||
| 			global $config; | 			global $config; | ||||||
| 
 | 
 | ||||||
| 			$this->sitemap_filepath = $_SERVER['DOCUMENT_ROOT'] . "/data/cache/sitemap.xml"; | 			$this->sitemap_filepath = $_SERVER['DOCUMENT_ROOT'] . "/data/cache/sitemap.xml"; | ||||||
| 			// determine if new sitemap needs to be generated
 | 			// determine if new sitemap needs to be generated
 | ||||||
|                 if ($this->new_sitemap_needed()) | 			if ($this->new_sitemap_needed()) { | ||||||
|                 { |  | ||||||
| 				// determine which type of sitemap to generate
 | 				// determine which type of sitemap to generate
 | ||||||
|                     if ($config->get_bool("sitemap_generatefull",false)) | 				if ($config->get_bool("sitemap_generatefull", false)) { | ||||||
| 					$this->handle_full_sitemap(); // default false until cache fixed
 | 					$this->handle_full_sitemap(); // default false until cache fixed
 | ||||||
|                     else | 				} else { | ||||||
| 					$this->handle_smaller_sitemap(); | 					$this->handle_smaller_sitemap(); | ||||||
| 				} | 				} | ||||||
|                 else $this->display_existing_sitemap(); | 			} else $this->display_existing_sitemap(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|         public function onSetupBuilding(SetupBuildingEvent $event) { | 	public function onSetupBuilding(SetupBuildingEvent $event) | ||||||
|  | 	{ | ||||||
| 		$sb = new SetupBlock("Sitemap"); | 		$sb = new SetupBlock("Sitemap"); | ||||||
| 
 | 
 | ||||||
| 		$sb->add_bool_option("sitemap_generatefull", "Generate full sitemap"); | 		$sb->add_bool_option("sitemap_generatefull", "Generate full sitemap"); | ||||||
| @ -48,9 +50,11 @@ class XMLSitemap extends Extension { | |||||||
| 		/* --- Add latest images to sitemap with higher priority --- */ | 		/* --- Add latest images to sitemap with higher priority --- */ | ||||||
| 		$latestimages = Image::find_images(0, 50, array()); | 		$latestimages = Image::find_images(0, 50, array()); | ||||||
| 		$latestimages_urllist = array(); | 		$latestimages_urllist = array(); | ||||||
|                 foreach($latestimages as $arrayid => $image) | 		foreach ($latestimages as $arrayid => $image) { | ||||||
| 			// create url from image id's
 | 			// create url from image id's
 | ||||||
| 			$latestimages_urllist[$arrayid] = "post/view/$image->id"; | 			$latestimages_urllist[$arrayid] = "post/view/$image->id"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		$this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", $image->posted_timestamp)); | 		$this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", $image->posted_timestamp)); | ||||||
| 
 | 
 | ||||||
| 		/* --- Display page --- */ | 		/* --- Display page --- */ | ||||||
| @ -79,9 +83,10 @@ class XMLSitemap extends Extension { | |||||||
| 		/* --- Add latest images to sitemap with higher priority --- */ | 		/* --- Add latest images to sitemap with higher priority --- */ | ||||||
| 		$latestimages = Image::find_images(0, 50, array()); | 		$latestimages = Image::find_images(0, 50, array()); | ||||||
| 		$latestimages_urllist = array(); | 		$latestimages_urllist = array(); | ||||||
|                 foreach($latestimages as $arrayid => $image) | 		foreach ($latestimages as $arrayid => $image) { | ||||||
| 			// create url from image id's
 | 			// create url from image id's
 | ||||||
| 			$latestimages_urllist[$arrayid] = "post/view/$image->id"; | 			$latestimages_urllist[$arrayid] = "post/view/$image->id"; | ||||||
|  | 		} | ||||||
| 		$this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", $image->posted_timestamp)); | 		$this->add_sitemap_queue($latestimages_urllist, "monthly", "0.8", date("Y-m-d", $image->posted_timestamp)); | ||||||
| 
 | 
 | ||||||
| 		/* --- Add other tags --- */ | 		/* --- Add other tags --- */ | ||||||
| @ -96,9 +101,10 @@ class XMLSitemap extends Extension { | |||||||
| 
 | 
 | ||||||
| 		/* --- Add all other images to sitemap with lower priority --- */ | 		/* --- Add all other images to sitemap with lower priority --- */ | ||||||
| 		$otherimages = Image::find_images(51, 10000000, array()); | 		$otherimages = Image::find_images(51, 10000000, array()); | ||||||
|                 foreach($otherimages as $arrayid => $image) | 		foreach ($otherimages as $arrayid => $image) { | ||||||
| 			// create url from image id's
 | 			// create url from image id's
 | ||||||
| 			$otherimages[$arrayid] = "post/view/$image->id"; | 			$otherimages[$arrayid] = "post/view/$image->id"; | ||||||
|  | 		} | ||||||
| 		$this->add_sitemap_queue($otherimages, "monthly", "0.6", date("Y-m-d", $image->posted_timestamp)); | 		$this->add_sitemap_queue($otherimages, "monthly", "0.6", date("Y-m-d", $image->posted_timestamp)); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -107,8 +113,17 @@ class XMLSitemap extends Extension { | |||||||
| 		$this->generate_display_sitemap(); | 		$this->generate_display_sitemap(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|         // Adds an array of urls to the sitemap with the given information
 | 	/** | ||||||
| 	private function add_sitemap_queue(/*array(urls)*/ $urls, $changefreq="monthly", $priority="0.5", $date="2013-02-01") { | 	 * Adds an array of urls to the sitemap with the given information. | ||||||
|  | 	 * | ||||||
|  | 	 * @param array $urls | ||||||
|  | 	 * @param string $changefreq | ||||||
|  | 	 * @param string $priority | ||||||
|  | 	 * @param string $date | ||||||
|  | 	 */ | ||||||
|  | 	private function add_sitemap_queue( /*array(urls)*/ $urls, $changefreq = "monthly", | ||||||
|  | 										$priority = "0.5", $date = "2013-02-01") | ||||||
|  | 	{ | ||||||
| 		foreach ($urls as $url) { | 		foreach ($urls as $url) { | ||||||
| 			$link = make_http(make_link("$url")); | 			$link = make_http(make_link("$url")); | ||||||
| 			$this->sitemap_queue .= " | 			$this->sitemap_queue .= " | ||||||
| @ -138,19 +153,27 @@ class XMLSitemap extends Extension { | |||||||
| 		$page->set_data($xml); | 		$page->set_data($xml); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|         // returns true if a new sitemap is needed
 | 	/** | ||||||
|  | 	 * Returns true if a new sitemap is needed. | ||||||
|  | 	 * | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function new_sitemap_needed() | 	private function new_sitemap_needed() | ||||||
| 	{ | 	{ | ||||||
| 		$sitemap_generation_interval = 86400; // allow new site map every day
 | 		$sitemap_generation_interval = 86400; // allow new site map every day
 | ||||||
| 		$last_generated_time = filemtime($this->sitemap_filepath); | 		$last_generated_time = filemtime($this->sitemap_filepath); | ||||||
| 
 | 
 | ||||||
| 		// if file doesn't exist, return true
 | 		// if file doesn't exist, return true
 | ||||||
|             if ($last_generated_time == false) return true; | 		if ($last_generated_time == false) { | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// if it's been a day since last sitemap creation, return true
 | 		// if it's been a day since last sitemap creation, return true
 | ||||||
|             if ($last_generated_time + $sitemap_generation_interval < time()) | 		if ($last_generated_time + $sitemap_generation_interval < time()) { | ||||||
| 			return true; | 			return true; | ||||||
|             else    return false; | 		} else { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private function display_existing_sitemap() | 	private function display_existing_sitemap() | ||||||
|  | |||||||
| @ -113,8 +113,9 @@ class Source_History extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * this function is called when a revert request is received | 	 * This function is called when a revert request is received. | ||||||
|  | 	 * @param int $revert_id | ||||||
| 	 */ | 	 */ | ||||||
| 	private function process_revert_request($revert_id) { | 	private function process_revert_request($revert_id) { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -202,6 +203,10 @@ class Source_History extends Extension { | |||||||
| 		$this->theme->display_revert_ip_results(); | 		$this->theme->display_revert_ip_results(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $revert_id | ||||||
|  | 	 * @return mixed|null | ||||||
|  | 	 */ | ||||||
| 	public function get_source_history_from_revert(/*int*/ $revert_id) { | 	public function get_source_history_from_revert(/*int*/ $revert_id) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$row = $database->get_row(" | 		$row = $database->get_row(" | ||||||
| @ -212,6 +217,10 @@ class Source_History extends Extension { | |||||||
| 		return ($row ? $row : null); | 		return ($row ? $row : null); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_source_history_from_id(/*int*/ $image_id) { | 	public function get_source_history_from_id(/*int*/ $image_id) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$row = $database->get_all(" | 		$row = $database->get_all(" | ||||||
| @ -224,6 +233,10 @@ class Source_History extends Extension { | |||||||
| 		return ($row ? $row : array()); | 		return ($row ? $row : array()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $page_id | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_global_source_history($page_id) { | 	public function get_global_source_history($page_id) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$row = $database->get_all(" | 		$row = $database->get_all(" | ||||||
| @ -236,8 +249,12 @@ class Source_History extends Extension { | |||||||
| 		return ($row ? $row : array()); | 		return ($row ? $row : array()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * This function attempts to revert all changes by a given IP within an (optional) timeframe. | 	 * This function attempts to revert all changes by a given IP within an (optional) timeframe. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $name | ||||||
|  | 	 * @param string $ip | ||||||
|  | 	 * @param string $date | ||||||
| 	 */ | 	 */ | ||||||
| 	public function process_revert_all_changes($name, $ip, $date) { | 	public function process_revert_all_changes($name, $ip, $date) { | ||||||
| 		global $database; | 		global $database; | ||||||
| @ -332,8 +349,10 @@ class Source_History extends Extension { | |||||||
| 		log_info("source_history", 'Reverted '.count($result).' edits.'); | 		log_info("source_history", 'Reverted '.count($result).' edits.'); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * this function is called just before an images source is changed | 	 * This function is called just before an images source is changed. | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param string $source | ||||||
| 	 */ | 	 */ | ||||||
| 	private function add_source_history($image, $source) { | 	private function add_source_history($image, $source) { | ||||||
| 		global $database, $config, $user; | 		global $database, $config, $user; | ||||||
|  | |||||||
| @ -2,6 +2,11 @@ | |||||||
| class Source_HistoryTheme extends Themelet { | class Source_HistoryTheme extends Themelet { | ||||||
| 	var $messages = array(); | 	var $messages = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param array $history | ||||||
|  | 	 */ | ||||||
| 	public function display_history_page(Page $page, /*int*/ $image_id, /*array*/ $history) { | 	public function display_history_page(Page $page, /*int*/ $image_id, /*array*/ $history) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 		$start_string = " | 		$start_string = " | ||||||
| @ -45,6 +50,11 @@ class Source_HistoryTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Source History", $history_html, "main", 10)); | 		$page->add_block(new Block("Source History", $history_html, "main", 10)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $history | ||||||
|  | 	 * @param int $page_number | ||||||
|  | 	 */ | ||||||
| 	public function display_global_page(Page $page, /*array*/ $history, /*int*/ $page_number) { | 	public function display_global_page(Page $page, /*array*/ $history, /*int*/ $page_number) { | ||||||
| 		$start_string = " | 		$start_string = " | ||||||
| 			<div style='text-align: left'> | 			<div style='text-align: left'> | ||||||
| @ -93,8 +103,9 @@ class Source_HistoryTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Navigation", $nav, "left")); | 		$page->add_block(new Block("Navigation", $nav, "left")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * Add a section to the admin page. | 	 * Add a section to the admin page. | ||||||
|  | 	 * @param string $validation_msg | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_admin_block(/*string*/ $validation_msg='') { | 	public function display_admin_block(/*string*/ $validation_msg='') { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -130,6 +141,10 @@ class Source_HistoryTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Bulk Revert Results", $html)); | 		$page->add_block(new Block("Bulk Revert Results", $html)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $title | ||||||
|  | 	 * @param string $body | ||||||
|  | 	 */ | ||||||
| 	public function add_status(/*string*/ $title, /*string*/ $body) { | 	public function add_status(/*string*/ $title, /*string*/ $body) { | ||||||
| 		$this->messages[] = '<p><b>'. $title .'</b><br>'. $body .'</p>'; | 		$this->messages[] = '<p><b>'. $title .'</b><br>'. $body .'</p>'; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ class StatsDInterface extends Extension { | |||||||
| 		$time = microtime(true) - $_load_start; | 		$time = microtime(true) - $_load_start; | ||||||
| 		StatsDInterface::$stats["shimmie.$type.hits"] = "1|c"; | 		StatsDInterface::$stats["shimmie.$type.hits"] = "1|c"; | ||||||
| 		StatsDInterface::$stats["shimmie.$type.time"] = "$time|ms"; | 		StatsDInterface::$stats["shimmie.$type.time"] = "$time|ms"; | ||||||
|  | 		StatsDInterface::$stats["shimmie.$type.time-db"] = "{$database->dbtime}|ms"; | ||||||
| 		StatsDInterface::$stats["shimmie.$type.memory"] = memory_get_peak_usage(true)."|c"; | 		StatsDInterface::$stats["shimmie.$type.memory"] = memory_get_peak_usage(true)."|c"; | ||||||
| 		StatsDInterface::$stats["shimmie.$type.files"] = count(get_included_files())."|c"; | 		StatsDInterface::$stats["shimmie.$type.files"] = count(get_included_files())."|c"; | ||||||
| 		StatsDInterface::$stats["shimmie.$type.queries"] = $_execs."|c"; | 		StatsDInterface::$stats["shimmie.$type.queries"] = $_execs."|c"; | ||||||
| @ -76,6 +77,9 @@ class StatsDInterface extends Extension { | |||||||
| 		StatsDInterface::$stats["shimmie.events.info-sets"] = "1|c"; | 		StatsDInterface::$stats["shimmie.events.info-sets"] = "1|c"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return int | ||||||
|  | 	 */ | ||||||
| 	public function get_priority() {return 99;} | 	public function get_priority() {return 99;} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -23,7 +23,14 @@ | |||||||
|  *      </ul> |  *      </ul> | ||||||
|  *    <li>Pools |  *    <li>Pools | ||||||
|  *      <ul> |  *      <ul> | ||||||
|  *        <li>pool=(PoolID, PoolTitle) -- add post to pool (if exists) |  *        <li>pool=(PoolID, PoolTitle, lastcreated) -- add post to pool (if exists) | ||||||
|  |  *        <li>pool=(PoolID, PoolTitle, lastcreated):(PoolOrder) -- add post to pool (if exists) with set pool order | ||||||
|  |  *        <ul> | ||||||
|  |  *          <li>pool=50 -- add post to pool with ID of 50 | ||||||
|  |  *          <li>pool=10:25 -- add post to pool with ID of 10 and with order 25 | ||||||
|  |  *          <li>pool=This_is_a_Pool -- add post to pool with a title of "This is a Pool" | ||||||
|  |  *          <li>pool=lastcreated -- add post to the last pool the user created | ||||||
|  |  *        </ul> | ||||||
|  *      </ul> |  *      </ul> | ||||||
|  *    <li>Post Relationships |  *    <li>Post Relationships | ||||||
|  *      <ul> |  *      <ul> | ||||||
| @ -40,9 +47,15 @@ | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class OwnerSetEvent extends Event { | class OwnerSetEvent extends Event { | ||||||
| 	var $image; | 	/** @var \Image  */ | ||||||
| 	var $owner; | 	public $image; | ||||||
|  | 	/** @var \User  */ | ||||||
|  | 	public $owner; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param User $owner | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Image $image, User $owner) { | 	public function __construct(Image $image, User $owner) { | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| 		$this->owner = $owner; | 		$this->owner = $owner; | ||||||
| @ -57,9 +70,15 @@ class OwnerSetEvent extends Event { | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class SourceSetEvent extends Event { | class SourceSetEvent extends Event { | ||||||
| 	var $image; | 	/** @var \Image */ | ||||||
| 	var $source; | 	public $image; | ||||||
|  | 	/** @var string */ | ||||||
|  | 	public $source; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param string $source | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Image $image, $source) { | 	public function __construct(Image $image, $source) { | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| 		$this->source = $source; | 		$this->source = $source; | ||||||
| @ -74,7 +93,8 @@ class SourceSetEvent extends Event { | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class TagSetEvent extends Event { | class TagSetEvent extends Event { | ||||||
| 	var $image; | 	/** @var \Image */ | ||||||
|  | 	public $image; | ||||||
| 	var $tags; | 	var $tags; | ||||||
| 
 | 
 | ||||||
| 	public function __construct(Image $image, $tags) { | 	public function __construct(Image $image, $tags) { | ||||||
| @ -90,9 +110,15 @@ class TagSetEvent extends Event { | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| class LockSetEvent extends Event { | class LockSetEvent extends Event { | ||||||
| 	var $image; | 	/** @var \Image */ | ||||||
| 	var $locked; | 	public $image; | ||||||
|  | 	/** @var bool */ | ||||||
|  | 	public $locked; | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param bool $locked | ||||||
|  | 	 */ | ||||||
| 	public function __construct(Image $image, $locked) { | 	public function __construct(Image $image, $locked) { | ||||||
| 		assert(is_bool($locked)); | 		assert(is_bool($locked)); | ||||||
| 		$this->image = $image; | 		$this->image = $image; | ||||||
| @ -107,13 +133,17 @@ class LockSetEvent extends Event { | |||||||
| class TagTermParseEvent extends Event { | class TagTermParseEvent extends Event { | ||||||
| 	var $term = null; | 	var $term = null; | ||||||
| 	var $id = null; | 	var $id = null; | ||||||
| 	var $metatag = false; | 	/** @var bool */ | ||||||
|  | 	public $metatag = false; | ||||||
| 
 | 
 | ||||||
| 	public function __construct($term, $id) { | 	public function __construct($term, $id) { | ||||||
| 		$this->term = $term; | 		$this->term = $term; | ||||||
| 		$this->id = $id; | 		$this->id = $id; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	public function is_metatag() { | 	public function is_metatag() { | ||||||
| 		return $this->metatag; | 		return $this->metatag; | ||||||
| 	} | 	} | ||||||
| @ -150,10 +180,14 @@ class TagEdit extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onImageInfoSet(ImageInfoSetEvent $event) { | 	public function onImageInfoSet(ImageInfoSetEvent $event) { | ||||||
| 		global $user, $page; | 		global $user; | ||||||
| 		if($user->can("edit_image_owner")) { | 		if($user->can("edit_image_owner")) { | ||||||
| 			$owner = User::by_name($_POST['tag_edit__owner']); | 			$owner = User::by_name($_POST['tag_edit__owner']); | ||||||
|  | 			if ($owner instanceof User) { | ||||||
| 				send_event(new OwnerSetEvent($event->image, $owner)); | 				send_event(new OwnerSetEvent($event->image, $owner)); | ||||||
|  | 			} else { | ||||||
|  | 				throw new NullUserException("Error: No user with that name was found."); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		if($this->can_tag($event->image) && isset($_POST['tag_edit__tags'])) { | 		if($this->can_tag($event->image) && isset($_POST['tag_edit__tags'])) { | ||||||
| 			send_event(new TagSetEvent($event->image, $_POST['tag_edit__tags'])); | 			send_event(new TagSetEvent($event->image, $_POST['tag_edit__tags'])); | ||||||
| @ -205,13 +239,15 @@ class TagEdit extends Extension { | |||||||
| 		$this->theme->display_mass_editor(); | 		$this->theme->display_mass_editor(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// When an alias is added, oldtag becomes inaccessable
 | 	/** | ||||||
|  | 	 * When an alias is added, oldtag becomes inaccessible. | ||||||
|  | 	 * @param AddAliasEvent $event | ||||||
|  | 	 */ | ||||||
| 	public function onAddAlias(AddAliasEvent $event) { | 	public function onAddAlias(AddAliasEvent $event) { | ||||||
| 		$this->mass_tag_edit($event->oldtag, $event->newtag); | 		$this->mass_tag_edit($event->oldtag, $event->newtag); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) { | 	public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) { | ||||||
| 		global $user; |  | ||||||
| 		$event->add_part($this->theme->get_user_editor_html($event->image), 39); | 		$event->add_part($this->theme->get_user_editor_html($event->image), 39); | ||||||
| 		$event->add_part($this->theme->get_tag_editor_html($event->image), 40); | 		$event->add_part($this->theme->get_tag_editor_html($event->image), 40); | ||||||
| 		$event->add_part($this->theme->get_source_editor_html($event->image), 41); | 		$event->add_part($this->theme->get_source_editor_html($event->image), 41); | ||||||
| @ -229,19 +265,30 @@ class TagEdit extends Extension { | |||||||
| 		if(!empty($matches)) $event->metatag = true; | 		if(!empty($matches)) $event->metatag = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function can_tag(Image $image) { | 	private function can_tag(Image $image) { | ||||||
| 		global $config, $user; | 		global $user; | ||||||
| 		return ($user->can("edit_image_tag") || !$image->is_locked()); | 		return ($user->can("edit_image_tag") || !$image->is_locked()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
| 	private function can_source(Image $image) { | 	private function can_source(Image $image) { | ||||||
| 		global $config, $user; | 		global $user; | ||||||
| 		return ($user->can("edit_image_source") || !$image->is_locked()); | 		return ($user->can("edit_image_source") || !$image->is_locked()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $search | ||||||
|  | 	 * @param string $replace | ||||||
|  | 	 */ | ||||||
| 	private function mass_tag_edit($search, $replace) { | 	private function mass_tag_edit($search, $replace) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		$search_set = Tag::explode(strtolower($search), false); | 		$search_set = Tag::explode(strtolower($search), false); | ||||||
| 		$replace_set = Tag::explode(strtolower($replace), false); | 		$replace_set = Tag::explode(strtolower($replace), false); | ||||||
| @ -296,10 +343,11 @@ class TagEdit extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string|string[] $tags | ||||||
|  | 	 * @param string $source | ||||||
|  | 	 */ | ||||||
| 	private function mass_source_edit($tags, $source) { | 	private function mass_source_edit($tags, $source) { | ||||||
| 		global $database; |  | ||||||
| 		global $config; |  | ||||||
| 
 |  | ||||||
| 		$tags = Tag::explode($tags); | 		$tags = Tag::explode($tags); | ||||||
| 
 | 
 | ||||||
| 		$last_id = -1; | 		$last_id = -1; | ||||||
|  | |||||||
| @ -99,6 +99,10 @@ class TagEditTheme extends Themelet { | |||||||
| 		";
 | 		";
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $source | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function format_source(/*string*/ $source) { | 	protected function format_source(/*string*/ $source) { | ||||||
| 		if(!empty($source)) { | 		if(!empty($source)) { | ||||||
| 			if(!startsWith($source, "http://") && !startsWith($source, "https://")) { | 			if(!startsWith($source, "http://") && !startsWith($source, "https://")) { | ||||||
|  | |||||||
| @ -51,7 +51,11 @@ class TagEditCloud extends Extension { | |||||||
| 		$event->panel->add_block($sb); | 		$event->panel->add_block($sb); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private function build_tag_map($image) { | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
|  | 	private function build_tag_map(Image $image) { | ||||||
| 		global $database, $config; | 		global $database, $config; | ||||||
| 
 | 
 | ||||||
| 		$html = ""; | 		$html = ""; | ||||||
| @ -75,9 +79,12 @@ class TagEditCloud extends Extension { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		$tag_data = null; | ||||||
|  | 
 | ||||||
| 		switch($sort_method){ | 		switch($sort_method){ | ||||||
| 			case 'a': | 			case 'a': | ||||||
| 			case 'p': | 			case 'p': | ||||||
|  | 			default: | ||||||
| 				$tag_data = $database->get_all("SELECT tag, FLOOR(LN(LN(count - :tag_min1 + 1)+1)*150)/200 AS scaled, count
 | 				$tag_data = $database->get_all("SELECT tag, FLOOR(LN(LN(count - :tag_min1 + 1)+1)*150)/200 AS scaled, count
 | ||||||
| 					FROM tags WHERE count >= :tag_min2 ORDER BY ".($sort_method == 'a' ? "tag" : "count DESC")." LIMIT :limit",
 | 					FROM tags WHERE count >= :tag_min2 ORDER BY ".($sort_method == 'a' ? "tag" : "count DESC")." LIMIT :limit",
 | ||||||
| 					array("tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count)); | 					array("tag_min1" => $tags_min, "tag_min2" => $tags_min, "limit" => $max_count)); | ||||||
| @ -115,15 +122,15 @@ class TagEditCloud extends Extension { | |||||||
| 			$size = sprintf("%.2f", max($row['scaled'],0.5)); | 			$size = sprintf("%.2f", max($row['scaled'],0.5)); | ||||||
| 			$js = htmlspecialchars('tageditcloud_toggle_tag(this,'.json_encode($full_tag).')',ENT_QUOTES); //Ugly, but it works
 | 			$js = htmlspecialchars('tageditcloud_toggle_tag(this,'.json_encode($full_tag).')',ENT_QUOTES); //Ugly, but it works
 | ||||||
| 
 | 
 | ||||||
| 			if(array_search($row['tag'],$image->tag_array) !== FALSE) { | 			if(array_search($row['tag'],$image->get_tag_array()) !== FALSE) { | ||||||
| 				if($used_first) { | 				if($used_first) { | ||||||
| 					$precloud .= " <span onclick='$js' class='tag-selected' style='font-size: ${size}em$color' title='${row['count']}'>$h_tag</span> \n"; | 					$precloud .= " <span onclick='{$js}' class='tag-selected' style='font-size: ${size}em$color' title='${row['count']}'>{$h_tag}</span> \n"; | ||||||
| 					continue; | 					continue; | ||||||
| 				} else { | 				} else { | ||||||
| 					$entry = " <span onclick='$js' class='tag-selected' style='font-size: ${size}em$color' title='${row['count']}'>$h_tag</span> \n"; | 					$entry = " <span onclick='{$js}' class='tag-selected' style='font-size: ${size}em$color' title='${row['count']}'>{$h_tag}</span> \n"; | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				$entry = " <span onclick='$js' style='font-size: ${size}em$color' title='${row['count']}'>$h_tag</span> \n"; | 				$entry = " <span onclick='{$js}' style='font-size: ${size}em$color' title='${row['count']}'>{$h_tag}</span> \n"; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if($counter++ <= $def_count) { | 			if($counter++ <= $def_count) { | ||||||
| @ -134,24 +141,28 @@ class TagEditCloud extends Extension { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if($precloud != '') { | 		if($precloud != '') { | ||||||
| 			$html .= "<div id='tagcloud_set'>$precloud</div>"; | 			$html .= "<div id='tagcloud_set'>{$precloud}</div>"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if($postcloud != '') { | 		if($postcloud != '') { | ||||||
| 			$postcloud = "<div id='tagcloud_extra' style='display: none;'>$postcloud</div>"; | 			$postcloud = "<div id='tagcloud_extra' style='display: none;'>{$postcloud}</div>"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$html .= "<div id='tagcloud_unset'>$cloud$postcloud</div>"; | 		$html .= "<div id='tagcloud_unset'>{$cloud}{$postcloud}</div>"; | ||||||
| 
 | 
 | ||||||
| 		if($sort_method != 'a' && $counter > $def_count) { | 		if($sort_method != 'a' && $counter > $def_count) { | ||||||
| 			$rem = $counter - $def_count; | 			$rem = $counter - $def_count; | ||||||
| 			$html .= "</div><br>[<span onclick='tageditcloud_toggle_extra(this);' style='color: #0000EF; font-weight:bold;'>show $rem more tags</span>]"; | 			$html .= "</div><br>[<span onclick='tageditcloud_toggle_extra(this);' style='color: #0000EF; font-weight:bold;'>show {$rem} more tags</span>]"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return "<div id='tageditcloud' class='tageditcloud'>$html</div>"; // FIXME: stupidasallhell
 | 		return "<div id='tageditcloud' class='tageditcloud'>{$html}</div>"; // FIXME: stupidasallhell
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private function can_tag($image) { | 	/** | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @return bool | ||||||
|  | 	 */ | ||||||
|  | 	private function can_tag(Image $image) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 		return ($user->can("edit_image_tag") && (!$image->is_locked() || $user->can("edit_image_lock"))); | 		return ($user->can("edit_image_tag") && (!$image->is_locked() || $user->can("edit_image_lock"))); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ class Tag_History extends Extension { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public function onPageRequest(PageRequestEvent $event) { | 	public function onPageRequest(PageRequestEvent $event) { | ||||||
| 		global $config, $page, $user; | 		global $page, $user; | ||||||
| 
 | 
 | ||||||
| 		if($event->page_matches("tag_history/revert")) { | 		if($event->page_matches("tag_history/revert")) { | ||||||
| 			// this is a request to revert to a previous version of the tags
 | 			// this is a request to revert to a previous version of the tags
 | ||||||
| @ -113,8 +113,11 @@ class Tag_History extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * this function is called when a revert request is received | 	 * This function is called when a revert request is received. | ||||||
|  | 	 * | ||||||
|  | 	 * @param int $revert_id | ||||||
|  | 	 * @throws ImageDoesNotExist | ||||||
| 	 */ | 	 */ | ||||||
| 	private function process_revert_request($revert_id) { | 	private function process_revert_request($revert_id) { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -200,6 +203,10 @@ class Tag_History extends Extension { | |||||||
| 		$this->theme->display_revert_ip_results(); | 		$this->theme->display_revert_ip_results(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $revert_id | ||||||
|  | 	 * @return mixed|null | ||||||
|  | 	 */ | ||||||
| 	public function get_tag_history_from_revert(/*int*/ $revert_id) { | 	public function get_tag_history_from_revert(/*int*/ $revert_id) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$row = $database->get_row(" | 		$row = $database->get_row(" | ||||||
| @ -210,6 +217,10 @@ class Tag_History extends Extension { | |||||||
| 		return ($row ? $row : null); | 		return ($row ? $row : null); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_tag_history_from_id(/*int*/ $image_id) { | 	public function get_tag_history_from_id(/*int*/ $image_id) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$row = $database->get_all(" | 		$row = $database->get_all(" | ||||||
| @ -222,6 +233,10 @@ class Tag_History extends Extension { | |||||||
| 		return ($row ? $row : array()); | 		return ($row ? $row : array()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $page_id | ||||||
|  | 	 * @return array | ||||||
|  | 	 */ | ||||||
| 	public function get_global_tag_history($page_id) { | 	public function get_global_tag_history($page_id) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$row = $database->get_all(" | 		$row = $database->get_all(" | ||||||
| @ -328,16 +343,19 @@ class Tag_History extends Extension { | |||||||
| 		log_info("tag_history", 'Reverted '.count($result).' edits.'); | 		log_info("tag_history", 'Reverted '.count($result).' edits.'); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * this function is called just before an images tag are changed | 	 * This function is called just before an images tag are changed. | ||||||
|  | 	 * | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 * @param string|string[] $tags | ||||||
| 	 */ | 	 */ | ||||||
| 	private function add_tag_history($image, $tags) { | 	private function add_tag_history(Image $image, $tags) { | ||||||
| 		global $database, $config, $user; | 		global $database, $config, $user; | ||||||
| 
 | 
 | ||||||
| 		$new_tags = Tag::implode($tags); | 		$new_tags = Tag::implode($tags); | ||||||
| 		$old_tags = Tag::implode($image->get_tag_array()); | 		$old_tags = Tag::implode($image->get_tag_array()); | ||||||
| 		 | 		 | ||||||
| 		if($new_tags == $old_tags) return; | 		if($new_tags == $old_tags) { return; } | ||||||
| 		 | 		 | ||||||
| 		if(empty($old_tags)) { | 		if(empty($old_tags)) { | ||||||
| 			/* no old tags, so we are probably adding the image for the first time */ | 			/* no old tags, so we are probably adding the image for the first time */ | ||||||
| @ -348,7 +366,7 @@ class Tag_History extends Extension { | |||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		$allowed = $config->get_int("history_limit"); | 		$allowed = $config->get_int("history_limit"); | ||||||
| 		if($allowed == 0) return; | 		if($allowed == 0) { return; } | ||||||
| 		 | 		 | ||||||
| 		// if the image has no history, make one with the old tags
 | 		// if the image has no history, make one with the old tags
 | ||||||
| 		$entries = $database->get_one("SELECT COUNT(*) FROM tag_histories WHERE image_id = ?", array($image->id)); | 		$entries = $database->get_one("SELECT COUNT(*) FROM tag_histories WHERE image_id = ?", array($image->id)); | ||||||
| @ -368,7 +386,7 @@ class Tag_History extends Extension { | |||||||
| 		$entries++; | 		$entries++; | ||||||
| 		 | 		 | ||||||
| 		// if needed remove oldest one
 | 		// if needed remove oldest one
 | ||||||
| 		if($allowed == -1) return; | 		if($allowed == -1) { return; } | ||||||
| 		if($entries > $allowed) { | 		if($entries > $allowed) { | ||||||
| 			// TODO: Make these queries better
 | 			// TODO: Make these queries better
 | ||||||
| 			/* | 			/* | ||||||
|  | |||||||
| @ -7,6 +7,11 @@ | |||||||
| class Tag_HistoryTheme extends Themelet { | class Tag_HistoryTheme extends Themelet { | ||||||
| 	var $messages = array(); | 	var $messages = array(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param int $image_id | ||||||
|  | 	 * @param array $history | ||||||
|  | 	 */ | ||||||
| 	public function display_history_page(Page $page, /*int*/ $image_id, /*array*/ $history) { | 	public function display_history_page(Page $page, /*int*/ $image_id, /*array*/ $history) { | ||||||
| 		global $user; | 		global $user; | ||||||
| 		$start_string = " | 		$start_string = " | ||||||
| @ -57,6 +62,11 @@ class Tag_HistoryTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Tag History", $history_html, "main", 10)); | 		$page->add_block(new Block("Tag History", $history_html, "main", 10)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param array $history | ||||||
|  | 	 * @param int $page_number | ||||||
|  | 	 */ | ||||||
| 	public function display_global_page(Page $page, /*array*/ $history, /*int*/ $page_number) { | 	public function display_global_page(Page $page, /*array*/ $history, /*int*/ $page_number) { | ||||||
| 		$start_string = " | 		$start_string = " | ||||||
| 			<div style='text-align: left'> | 			<div style='text-align: left'> | ||||||
| @ -105,8 +115,10 @@ class Tag_HistoryTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Navigation", $nav, "left")); | 		$page->add_block(new Block("Navigation", $nav, "left")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* | 	/** | ||||||
| 	 * Add a section to the admin page. | 	 * Add a section to the admin page. | ||||||
|  | 	 * | ||||||
|  | 	 * @param string $validation_msg | ||||||
| 	 */ | 	 */ | ||||||
| 	public function display_admin_block(/*string*/ $validation_msg='') { | 	public function display_admin_block(/*string*/ $validation_msg='') { | ||||||
| 		global $page; | 		global $page; | ||||||
| @ -142,6 +154,10 @@ class Tag_HistoryTheme extends Themelet { | |||||||
| 		$page->add_block(new Block("Bulk Revert Results", $html)); | 		$page->add_block(new Block("Bulk Revert Results", $html)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $title | ||||||
|  | 	 * @param string $body | ||||||
|  | 	 */ | ||||||
| 	public function add_status(/*string*/ $title, /*string*/ $body) { | 	public function add_status(/*string*/ $title, /*string*/ $body) { | ||||||
| 		$this->messages[] = '<p><b>'. $title .'</b><br>'. $body .'</p>'; | 		$this->messages[] = '<p><b>'. $title .'</b><br>'. $body .'</p>'; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -121,6 +121,10 @@ class TagList extends Extension { | |||||||
| 	} | 	} | ||||||
| // }}}
 | // }}}
 | ||||||
| // misc {{{
 | // misc {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function tag_link(/*string*/ $tag) { | 	private function tag_link(/*string*/ $tag) { | ||||||
| 		$u_tag = url_escape($tag); | 		$u_tag = url_escape($tag); | ||||||
| 		return make_link("post/list/$u_tag/1"); | 		return make_link("post/list/$u_tag/1"); | ||||||
| @ -129,7 +133,8 @@ class TagList extends Extension { | |||||||
| 	/** | 	/** | ||||||
| 	 * Get the minimum number of times a tag needs to be used | 	 * Get the minimum number of times a tag needs to be used | ||||||
| 	 * in order to be considered in the tag list. | 	 * in order to be considered in the tag list. | ||||||
| 	 * @retval int | 	 * | ||||||
|  | 	 * @return int | ||||||
| 	 */ | 	 */ | ||||||
| 	private function get_tags_min() { | 	private function get_tags_min() { | ||||||
| 		if(isset($_GET['mincount'])) { | 		if(isset($_GET['mincount'])) { | ||||||
| @ -141,6 +146,9 @@ class TagList extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function get_starts_with() { | 	private function get_starts_with() { | ||||||
| 		global $config; | 		global $config; | ||||||
| 		if(isset($_GET['starts_with'])) { | 		if(isset($_GET['starts_with'])) { | ||||||
| @ -156,6 +164,9 @@ class TagList extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function build_az() { | 	private function build_az() { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| @ -179,6 +190,10 @@ class TagList extends Extension { | |||||||
| 	} | 	} | ||||||
| // }}}
 | // }}}
 | ||||||
| // maps {{{
 | // maps {{{
 | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function build_navigation() { | 	private function build_navigation() { | ||||||
| 		$h_index = "<a href='".make_link()."'>Index</a>"; | 		$h_index = "<a href='".make_link()."'>Index</a>"; | ||||||
| 		$h_map = "<a href='".make_link("tags/map")."'>Map</a>"; | 		$h_map = "<a href='".make_link("tags/map")."'>Map</a>"; | ||||||
| @ -189,6 +204,9 @@ class TagList extends Extension { | |||||||
| 		return "$h_index<br> <br>$h_map<br>$h_alphabetic<br>$h_popularity<br>$h_cats<br> <br>$h_all"; | 		return "$h_index<br> <br>$h_map<br>$h_alphabetic<br>$h_popularity<br>$h_cats<br> <br>$h_all"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function build_tag_map() { | 	private function build_tag_map() { | ||||||
| 		global $config, $database; | 		global $config, $database; | ||||||
| 
 | 
 | ||||||
| @ -226,6 +244,9 @@ class TagList extends Extension { | |||||||
| 		return $html; | 		return $html; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function build_tag_alphabetic() { | 	private function build_tag_alphabetic() { | ||||||
| 		global $config, $database; | 		global $config, $database; | ||||||
| 
 | 
 | ||||||
| @ -279,6 +300,9 @@ class TagList extends Extension { | |||||||
| 		return $html; | 		return $html; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function build_tag_popularity() { | 	private function build_tag_popularity() { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| @ -318,6 +342,9 @@ class TagList extends Extension { | |||||||
| 		return $html; | 		return $html; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	private function build_tag_list() { | 	private function build_tag_list() { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| @ -344,9 +371,12 @@ class TagList extends Extension { | |||||||
| 	} | 	} | ||||||
| // }}}
 | // }}}
 | ||||||
| // blocks {{{
 | // blocks {{{
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 */ | ||||||
| 	private function add_related_block(Page $page, Image $image) { | 	private function add_related_block(Page $page, Image $image) { | ||||||
| 		global $database; | 		global $database, $config; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		$query = " | 		$query = " | ||||||
| 			SELECT t3.tag AS tag, t3.count AS calc_count, it3.tag_id | 			SELECT t3.tag AS tag, t3.count AS calc_count, it3.tag_id | ||||||
| @ -376,9 +406,12 @@ class TagList extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 */ | ||||||
| 	private function add_split_tags_block(Page $page, Image $image) { | 	private function add_split_tags_block(Page $page, Image $image) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		$query = " | 		$query = " | ||||||
| 			SELECT tags.tag, tags.count as calc_count | 			SELECT tags.tag, tags.count as calc_count | ||||||
| @ -395,9 +428,12 @@ class TagList extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param Image $image | ||||||
|  | 	 */ | ||||||
| 	private function add_tags_block(Page $page, Image $image) { | 	private function add_tags_block(Page $page, Image $image) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		$query = " | 		$query = " | ||||||
| 			SELECT tags.tag, tags.count as calc_count | 			SELECT tags.tag, tags.count as calc_count | ||||||
| @ -414,9 +450,11 @@ class TagList extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 */ | ||||||
| 	private function add_popular_block(Page $page) { | 	private function add_popular_block(Page $page) { | ||||||
| 		global $database; | 		global $database, $config; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		$tags = $database->cache->get("popular_tags"); | 		$tags = $database->cache->get("popular_tags"); | ||||||
| 		if(empty($tags)) { | 		if(empty($tags)) { | ||||||
| @ -437,9 +475,12 @@ class TagList extends Extension { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param Page $page | ||||||
|  | 	 * @param string[] $search | ||||||
|  | 	 */ | ||||||
| 	private function add_refine_block(Page $page, /*array(string)*/ $search) { | 	private function add_refine_block(Page $page, /*array(string)*/ $search) { | ||||||
| 		global $database; | 		global $database, $config; | ||||||
| 		global $config; |  | ||||||
| 
 | 
 | ||||||
| 		$wild_tags = Tag::explode($search); | 		$wild_tags = Tag::explode($search); | ||||||
| 		$str_search = Tag::implode($search); | 		$str_search = Tag::implode($search); | ||||||
|  | |||||||
| @ -1,13 +1,23 @@ | |||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| class TagListTheme extends Themelet { | class TagListTheme extends Themelet { | ||||||
| 	var $heading = ""; | 	/** @var string  */ | ||||||
| 	var $list = ""; | 	public $heading = ""; | ||||||
|  | 	/** @var string|string[]  */ | ||||||
|  | 	public $list = ""; | ||||||
| 
 | 
 | ||||||
|  | 	public $navigation; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $text | ||||||
|  | 	 */ | ||||||
| 	public function set_heading($text) { | 	public function set_heading($text) { | ||||||
| 		$this->heading = $text; | 		$this->heading = $text; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string|string[] $list | ||||||
|  | 	 */ | ||||||
| 	public function set_tag_list($list) { | 	public function set_tag_list($list) { | ||||||
| 		$this->list = $list; | 		$this->list = $list; | ||||||
| 	} | 	} | ||||||
| @ -219,6 +229,11 @@ class TagListTheme extends Themelet { | |||||||
| 		return array($category, $display_html); | 		return array($category, $display_html); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @param string[] $tags | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function ars(/*string*/ $tag, /*array(string)*/ $tags) { | 	protected function ars(/*string*/ $tag, /*array(string)*/ $tags) { | ||||||
| 		assert(is_array($tags)); | 		assert(is_array($tags)); | ||||||
| 
 | 
 | ||||||
| @ -234,6 +249,11 @@ class TagListTheme extends Themelet { | |||||||
| 		return $html; | 		return $html; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $tags | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function get_remove_link($tags, $tag) { | 	protected function get_remove_link($tags, $tag) { | ||||||
| 		if(!in_array($tag, $tags) && !in_array("-$tag", $tags)) { | 		if(!in_array($tag, $tags) && !in_array("-$tag", $tags)) { | ||||||
| 			return ""; | 			return ""; | ||||||
| @ -245,6 +265,11 @@ class TagListTheme extends Themelet { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $tags | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function get_add_link($tags, $tag) { | 	protected function get_add_link($tags, $tag) { | ||||||
| 		if(in_array($tag, $tags)) { | 		if(in_array($tag, $tags)) { | ||||||
| 			return ""; | 			return ""; | ||||||
| @ -256,6 +281,11 @@ class TagListTheme extends Themelet { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array $tags | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function get_subtract_link($tags, $tag) { | 	protected function get_subtract_link($tags, $tag) { | ||||||
| 		if(in_array("-$tag", $tags)) { | 		if(in_array("-$tag", $tags)) { | ||||||
| 			return ""; | 			return ""; | ||||||
| @ -267,6 +297,10 @@ class TagListTheme extends Themelet { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param string $tag | ||||||
|  | 	 * @return string | ||||||
|  | 	 */ | ||||||
| 	protected function tag_link($tag) { | 	protected function tag_link($tag) { | ||||||
| 		$u_tag = url_escape($tag); | 		$u_tag = url_escape($tag); | ||||||
| 		return make_link("post/list/$u_tag/1"); | 		return make_link("post/list/$u_tag/1"); | ||||||
|  | |||||||
| @ -132,10 +132,13 @@ class Tips extends Extension { | |||||||
| 		$this->theme->showAll($url, $tips); | 		$this->theme->showAll($url, $tips); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $tipID | ||||||
|  | 	 */ | ||||||
| 	private function setStatus($tipID) { | 	private function setStatus($tipID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 
 | 
 | ||||||
| 		$tip = $database->get_row("SELECT * FROM tips WHERE id = ? ", array($tipID)); | 		$tip = $database->get_row("SELECT * FROM tips WHERE id = ? ", array(int_escape($tipID))); | ||||||
| 
 | 
 | ||||||
| 		if (bool_escape($tip['enable'])) { | 		if (bool_escape($tip['enable'])) { | ||||||
| 			$enable = "N"; | 			$enable = "N"; | ||||||
| @ -143,12 +146,15 @@ class Tips extends Extension { | |||||||
| 			$enable = "Y"; | 			$enable = "Y"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$database->execute("UPDATE tips SET enable = ? WHERE id = ?", array ($enable, $tipID)); | 		$database->execute("UPDATE tips SET enable = ? WHERE id = ?", array ($enable, int_escape($tipID))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param int $tipID | ||||||
|  | 	 */ | ||||||
| 	private function deleteTip($tipID) { | 	private function deleteTip($tipID) { | ||||||
| 		global $database; | 		global $database; | ||||||
| 		$database->execute("DELETE FROM tips WHERE id = ?", array($tipID)); | 		$database->execute("DELETE FROM tips WHERE id = ?", array(int_escape($tipID))); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,24 +0,0 @@ | |||||||
| <?php |  | ||||||
| /* |  | ||||||
|  * Name: Tweet! |  | ||||||
|  * Author: Shish <webmaster@shishnet.org> |  | ||||||
|  * Link: http://code.shishnet.org/shimmie2/ |  | ||||||
|  * License: GPLv2 |  | ||||||
|  * Description: Show a twitter feed with the Sea of Clouds script |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| class TwitterSoc extends Extension { |  | ||||||
| 	public function onPostListBuilding(PostListBuildingEvent $event) { |  | ||||||
| 		global $config, $page; |  | ||||||
| 		if(strlen($config->get_string("twitter_soc_username")) > 0) { |  | ||||||
| 			$this->theme->display_feed($page, $config->get_string("twitter_soc_username")); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	public function onSetupBuilding(SetupBuildingEvent $event) { |  | ||||||
| 		$sb = new SetupBlock("Tweet!"); |  | ||||||
| 		$sb->add_text_option("twitter_soc_username", "Username "); |  | ||||||
| 		$event->panel->add_block($sb); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user