* New helper class for dealing with forms
authorNiklas Laxström <nikerabbit@users.mediawiki.org>
Sat, 19 Apr 2008 17:38:06 +0000 (17:38 +0000)
committerNiklas Laxström <nikerabbit@users.mediawiki.org>
Sat, 19 Apr 2008 17:38:06 +0000 (17:38 +0000)
includes/AutoLoader.php
includes/FormOptions.php [new file with mode: 0644]

index 3d43865..14c54f7 100644 (file)
@@ -97,6 +97,7 @@ function __autoload($className) {
                'FileRevertForm' => 'includes/FileRevertForm.php',
                'FileStore' => 'includes/FileStore.php',
                'FormatExif' => 'includes/Exif.php',
+               'FormOptions' => 'includes/FormOptions.php',
                'FSException' => 'includes/FileStore.php',
                'FSTransaction' => 'includes/FileStore.php',
                'HashBagOStuff' => 'includes/BagOStuff.php',
diff --git a/includes/FormOptions.php b/includes/FormOptions.php
new file mode 100644 (file)
index 0000000..f708b4a
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+/**
+ * Helper class to keep track of options when mixing links and form elements.
+ *
+ * @author Niklas Laxström
+ * @copyright Copyright © 2008, Niklas Laxström
+ */
+
+class FormOptions {
+       const AUTO = -1; //! Automatically detects simple data types
+       const STRING = 0;
+       const INT = 1;
+       const BOOL = 2;
+       const INTNULL = 3; //! Useful for namespace selector
+
+       protected $options = array();
+
+       # Setting up
+
+       public function add( $name, $default, $type = self::AUTO ) {
+               $option = array();
+               $option['default'] = $default;
+               $option['value'] = null;
+               $option['consumed'] = false;
+
+               if ( $type !== self::AUTO ) {
+                       $option['type'] = $type;
+               } else {
+                       $option['type'] = self::guessType( $default );
+               }
+
+               $this->options[$name] = $option;
+       }
+
+       public static function guessType( $data ) {
+               if ( is_bool($data) ) {
+                       return self::BOOL;
+               } elseif( is_int($data) ) {
+                       return self::INT;
+               } elseif( is_string($data) ) {
+                       return self::STRING;
+               } else {
+                       throw new MWException( 'Unsupported datatype' );
+               }
+       }
+
+       # Handling values
+
+       public function validateName( $name, $strict = false ) {
+               if ( !isset($this->options[$name]) ) {
+                       if ( $strict ) {
+                               throw new MWException( "Invalid option $name" );
+                       } else {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       public function setValue( $name, $value, $force = false ) {
+               $this->validateName( $name, true );
+               if ( !$force && $value === $this->options[$name]['default'] ) {
+                       // null default values as unchanged
+                       $this->options[$name]['value'] = null;
+               } else {
+                       $this->options[$name]['value'] = $value;
+               }
+       }
+
+       public function getValue( $name ) {
+               $this->validateName( $name, true );
+               return $this->getValueReal( $this->options[$name] );
+       }
+
+       protected function getValueReal( $option ) {
+               if ( $option['value'] !== null ) {
+                       return $option['value'];
+               } else {
+                       return $option['default'];
+               }
+       }
+
+       public function consumeValue( $name ) {
+               $this->validateName( $name, true );
+               $this->options[$name]['consumed'] = true;
+               return $this->getValueReal( $this->options[$name] );
+       }
+
+       public function consumeValues( /*Array*/ $names ) {
+               $out = array();
+               foreach ( $names as $name ) {
+                       $this->validateName( $name, true );
+                       $this->options[$name]['consumed'] = true;
+                       $out[] = $this->getValueReal( $this->options[$name] );
+               }
+               return $out;
+       }
+
+       # Validating values
+
+       public function validateIntBounds( $name, $min, $max ) {
+               $this->validateName( $name, true );
+
+               if ( $this->options[$name]['type'] !== self::INT )
+                       throw new MWException( "Option $name is not of type int" );
+
+               $value = $this->getValueReal( $this->options[$name] );
+               $value = max( $min, min( $max, $value ) );
+
+               $this->setValue( $name, $value );
+       }
+
+       # Getting the data out for use
+
+       public function getUnconsumedValues( $all = false ) {
+               $values = array();
+               foreach ( $this->options as $name => $data ) {
+                       if ( !$data['consumed'] ) {
+                               if ( $all || $data['value'] !== null ) {
+                                       $values[$name] = $this->getValueReal( $data );
+                               }
+                       }
+               }
+               return $values;
+       }
+
+       public function getChangedValues() {
+               $values = array();
+               foreach ( $this->options as $name => $data ) {
+                       if ( $data['value'] !== null ) {
+                               $values[$name] = $data['value'];
+                       }
+               }
+               return $values;
+       }
+
+       # Reading values
+
+       public function fetchValuesFromRequest( WebRequest $r ) {
+               foreach ( array_keys($this->options) as $name ) {
+                       $default = $this->options[$name]['default'];
+                       $type = $this->options[$name]['type'];
+
+                       switch( $type ) {
+                               case self::BOOL:
+                                       $value = $r->getBool( $name, $default ); break;
+                               case self::INT:
+                                       $value = $r->getInt( $name, $default ); break;
+                               case self::STRING:
+                                       $value = $r->getText( $name, $default ); break;
+                               case self::INTNULL:
+                                       $value = $r->getIntOrNull( $name ); break;
+                               default:
+                                       throw new MWException( 'Unsupported datatype' );
+                       }
+
+                       if ( $value !== $default && $value != null ) {
+                               $this->options[$name]['value'] = $value;
+                       }
+               }
+       }
+
+}
\ No newline at end of file