r111468 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111467‎ | r111468 | r111469 >
Date:18:11, 14 February 2012
Author:jeroendedauw
Status:reverted (Comments)
Tags:
Comment:
follow up to r111264; split up class into one representing a table and one representing rows. Also getting rid of staticness, in particular LSB, so this becomes PHP 5.2 compatible. Not done yet, will follow up later
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/DBDataObject.php (modified) (history)
  • /trunk/phase3/includes/DBTable.php (added) (history)

Diff [purge]

Index: trunk/phase3/includes/DBDataObject.php
@@ -54,6 +54,12 @@
5555 protected $fields = array( 'id' => null );
5656
5757 /**
 58+ * @since 1.20
 59+ * @var DBTable
 60+ */
 61+ protected $table;
 62+
 63+ /**
5864 * If the object should update summaries of linked items when changed.
5965 * For example, update the course_count field in universities when a course in courses is deleted.
6066 * Settings this to false can prevent needless updating work in situations
@@ -73,7 +79,6 @@
7480 * @var bool
7581 */
7682 protected $inSummaryMode = false;
77 -
7883
7984 /**
8085 * The database connection to use for read operations.
@@ -82,81 +87,9 @@
8388 * @since 1.20
8489 * @var integer DB_ enum
8590 */
86 - protected static $readDb = DB_SLAVE;
87 -
88 - /**
89 - * Returns the name of the database table objects of this type are stored in.
90 - *
91 - * @since 1.20
92 - *
93 - * @throws MWException
94 - * @return string
95 - */
96 - public static function getDBTable() {
97 - throw new MWException( 'Class "' . get_called_class() . '" did not implement getDBTable' );
98 - }
99 -
100 - /**
101 - * Gets the db field prefix.
102 - *
103 - * @since 1.20
104 - *
105 - * @throws MWException
106 - * @return string
107 - */
108 - protected static function getFieldPrefix() {
109 - throw new MWException( 'Class "' . get_called_class() . '" did not implement getFieldPrefix' );
110 - }
111 -
112 - /**
113 - * Returns an array with the fields and their types this object contains.
114 - * This corresponds directly to the fields in the database, without prefix.
115 - *
116 - * field name => type
117 - *
118 - * Allowed types:
119 - * * id
120 - * * str
121 - * * int
122 - * * float
123 - * * bool
124 - * * array
125 - *
126 - * @since 1.20
127 - *
128 - * @throws MWException
129 - * @return array
130 - */
131 - protected static function getFieldTypes() {
132 - throw new MWException( 'Class did not implement getFieldTypes' );
133 - }
134 -
135 - /**
136 - * Returns a list of default field values.
137 - * field name => field value
138 - *
139 - * @since 1.20
140 - *
141 - * @return array
142 - */
143 - public static function getDefaults() {
144 - return array();
145 - }
 91+ protected $readDb = DB_SLAVE;
14692
14793 /**
148 - * Returns a list of the summary fields.
149 - * These are fields that cache computed values, such as the amount of linked objects of $type.
150 - * This is relevant as one might not want to do actions such as log changes when these get updated.
151 - *
152 - * @since 1.20
153 - *
154 - * @return array
155 - */
156 - public static function getSummaryFields() {
157 - return array();
158 - }
159 -
160 - /**
16194 * Constructor.
16295 *
16396 * @since 1.20
@@ -164,13 +97,15 @@
16598 * @param array|null $fields
16699 * @param boolean $loadDefaults
167100 */
168 - public function __construct( $fields = null, $loadDefaults = false ) {
 101+ public function __construct( DBTable $table, $fields = null, $loadDefaults = false ) {
 102+ $this->table = $table;
 103+
169104 if ( !is_array( $fields ) ) {
170105 $fields = array();
171106 }
172107
173108 if ( $loadDefaults ) {
174 - $fields = array_merge( $this->getDefaults(), $fields );
 109+ $fields = array_merge( $this->table->getDefaults(), $fields );
175110 }
176111
177112 $this->setFields( $fields );
@@ -549,7 +484,7 @@
550485 * @throws MWException
551486 */
552487 public function setField( $name, $value ) {
553 - $fields = $this->getFieldTypes();
 488+ $fields = $this->table->getFieldTypes();
554489
555490 if ( array_key_exists( $name, $fields ) ) {
556491 switch ( $fields[$name] ) {
@@ -603,18 +538,19 @@
604539 *
605540 * @return DBDataObject
606541 */
607 - public static function newFromArray( array $data, $loadDefaults = false ) {
608 - return new static( $data, $loadDefaults );
 542+ public function newFromArray( array $data, $loadDefaults = false ) {
 543+ return new self( $data, $loadDefaults );
609544 }
610545
611546 /**
612547 * Get the database type used for read operations.
613548 *
614549 * @since 1.20
 550+ *
615551 * @return integer DB_ enum
616552 */
617 - public static function getReadDb() {
618 - return self::$readDb;
 553+ public function getReadDb() {
 554+ return $this->readDb;
619555 }
620556
621557 /**
@@ -624,8 +560,8 @@
625561 *
626562 * @since 1.20
627563 */
628 - public static function setReadDb( $db ) {
629 - self::$readDb = $db;
 564+ public function setReadDb( $db ) {
 565+ $this->readDb = $db;
630566 }
631567
632568 /**
@@ -637,156 +573,11 @@
638574 *
639575 * @return boolean
640576 */
641 - public static function canHaveField( $name ) {
642 - return array_key_exists( $name, static::getFieldTypes() );
 577+ public function canHaveField( $name ) {
 578+ return array_key_exists( $name, $this->table->getFieldTypes() );
643579 }
644580
645581 /**
646 - * Takes in a field or array of fields and returns an
647 - * array with their prefixed versions, ready for db usage.
648 - *
649 - * @since 1.20
650 - *
651 - * @param array|string $fields
652 - *
653 - * @return array
654 - */
655 - public static function getPrefixedFields( array $fields ) {
656 - foreach ( $fields as &$field ) {
657 - $field = static::getPrefixedField( $field );
658 - }
659 -
660 - return $fields;
661 - }
662 -
663 - /**
664 - * Takes in a field and returns an it's prefixed version, ready for db usage.
665 - *
666 - * @since 1.20
667 - *
668 - * @param string|array $field
669 - *
670 - * @return string
671 - * @throws MWException
672 - */
673 - public static function getPrefixedField( $field ) {
674 - return static::getFieldPrefix() . $field;
675 - }
676 -
677 - /**
678 - * Takes in an associative array with field names as keys and
679 - * their values as value. The field names are prefixed with the
680 - * db field prefix.
681 - *
682 - * Field names can also be provided as an array with as first element a table name, such as
683 - * $conditions = array(
684 - * array( array( 'tablename', 'fieldname' ), $value ),
685 - * );
686 - *
687 - * @since 1.20
688 - *
689 - * @param array $values
690 - *
691 - * @return array
692 - */
693 - public static function getPrefixedValues( array $values ) {
694 - $prefixedValues = array();
695 -
696 - foreach ( $values as $field => $value ) {
697 - if ( is_integer( $field ) ) {
698 - if ( is_array( $value ) ) {
699 - $field = $value[0];
700 - $value = $value[1];
701 - }
702 - else {
703 - $value = explode( ' ', $value, 2 );
704 - $value[0] = static::getPrefixedField( $value[0] );
705 - $prefixedValues[] = implode( ' ', $value );
706 - continue;
707 - }
708 - }
709 -
710 - $prefixedValues[static::getPrefixedField( $field )] = $value;
711 - }
712 -
713 - return $prefixedValues;
714 - }
715 -
716 - /**
717 - * Get an array with fields from a database result,
718 - * that can be fed directly to the constructor or
719 - * to setFields.
720 - *
721 - * @since 1.20
722 - *
723 - * @param object $result
724 - *
725 - * @return array
726 - */
727 - public static function getFieldsFromDBResult( $result ) {
728 - $result = (array)$result;
729 - return array_combine(
730 - static::unprefixFieldNames( array_keys( $result ) ),
731 - array_values( $result )
732 - );
733 - }
734 -
735 - /**
736 - * Takes a field name with prefix and returns the unprefixed equivalent.
737 - *
738 - * @since 1.20
739 - *
740 - * @param string $fieldName
741 - *
742 - * @return string
743 - */
744 - public static function unprefixFieldName( $fieldName ) {
745 - return substr( $fieldName, strlen( static::getFieldPrefix() ) );
746 - }
747 -
748 - /**
749 - * Takes an array of field names with prefix and returns the unprefixed equivalent.
750 - *
751 - * @since 1.20
752 - *
753 - * @param array $fieldNames
754 - *
755 - * @return array
756 - */
757 - public static function unprefixFieldNames( array $fieldNames ) {
758 - return array_map( 'static::unprefixFieldName', $fieldNames );
759 - }
760 -
761 - /**
762 - * Get a new instance of the class from a database result.
763 - *
764 - * @since 1.20
765 - *
766 - * @param stdClass $result
767 - *
768 - * @return DBDataObject
769 - */
770 - public static function newFromDBResult( stdClass $result ) {
771 - return static::newFromArray( static::getFieldsFromDBResult( $result ) );
772 - }
773 -
774 - /**
775 - * Removes the object from the database.
776 - *
777 - * @since 1.20
778 - *
779 - * @param array $conditions
780 - *
781 - * @return boolean Success indicator
782 - */
783 - public static function delete( array $conditions ) {
784 - return wfGetDB( DB_MASTER )->delete(
785 - static::getDBTable(),
786 - static::getPrefixedValues( $conditions )
787 - );
788 - }
789 -
790 - /**
791582 * Add an amount (can be negative) to the specified field (needs to be numeric).
792583 *
793584 * @since 1.20
@@ -796,12 +587,12 @@
797588 *
798589 * @return boolean Success indicator
799590 */
800 - public static function addToField( $field, $amount ) {
 591+ public function addToField( $field, $amount ) {
801592 if ( $amount == 0 ) {
802593 return true;
803594 }
804595
805 - if ( !static::hasIdField() ) {
 596+ if ( !$this->hasIdField() ) {
806597 return false;
807598 }
808599
@@ -810,12 +601,12 @@
811602
812603 $dbw = wfGetDB( DB_MASTER );
813604
814 - $fullField = static::getPrefixedField( $field );
 605+ $fullField = $this->getPrefixedField( $field );
815606
816607 $success = $dbw->update(
817 - static::getDBTable(),
 608+ $this->getDBTable(),
818609 array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
819 - array( static::getPrefixedField( 'id' ) => static::getId() ),
 610+ array( $this->getPrefixedField( 'id' ) => $this->getId() ),
820611 __METHOD__
821612 );
822613
@@ -828,171 +619,6 @@
829620
830621 /**
831622 * Selects the the specified fields of the records matching the provided
832 - * conditions and returns them as DBDataObject. Field names get prefixed.
833 - *
834 - * @since 1.20
835 - *
836 - * @param array|string|null $fields
837 - * @param array $conditions
838 - * @param array $options
839 - *
840 - * @return array of self
841 - */
842 - public static function select( $fields = null, array $conditions = array(), array $options = array() ) {
843 - $result = static::selectFields( $fields, $conditions, $options, false );
844 -
845 - $objects = array();
846 -
847 - foreach ( $result as $record ) {
848 - $objects[] = static::newFromArray( $record );
849 - }
850 -
851 - return $objects;
852 - }
853 -
854 - /**
855 - * Selects the the specified fields of the records matching the provided
856 - * conditions and returns them as associative arrays.
857 - * Provided field names get prefixed.
858 - * Returned field names will not have a prefix.
859 - *
860 - * When $collapse is true:
861 - * If one field is selected, each item in the result array will be this field.
862 - * If two fields are selected, each item in the result array will have as key
863 - * the first field and as value the second field.
864 - * If more then two fields are selected, each item will be an associative array.
865 - *
866 - * @since 1.20
867 - *
868 - * @param array|string|null $fields
869 - * @param array $conditions
870 - * @param array $options
871 - * @param boolean $collapse Set to false to always return each result row as associative array.
872 - *
873 - * @return array of array
874 - */
875 - public static function selectFields( $fields = null, array $conditions = array(), array $options = array(), $collapse = true ) {
876 - if ( is_null( $fields ) ) {
877 - $fields = array_keys( static::getFieldTypes() );
878 - }
879 - else {
880 - $fields = (array)$fields;
881 - }
882 -
883 - $dbr = wfGetDB( static::getReadDb() );
884 - $result = $dbr->select(
885 - static::getDBTable(),
886 - static::getPrefixedFields( $fields ),
887 - static::getPrefixedValues( $conditions ),
888 - __METHOD__,
889 - $options
890 - );
891 -
892 - $objects = array();
893 -
894 - foreach ( $result as $record ) {
895 - $objects[] = static::getFieldsFromDBResult( $record );
896 - }
897 -
898 - if ( $collapse ) {
899 - if ( count( $fields ) === 1 ) {
900 - $objects = array_map( 'array_shift', $objects );
901 - }
902 - elseif ( count( $fields ) === 2 ) {
903 - $o = array();
904 -
905 - foreach ( $objects as $object ) {
906 - $o[array_shift( $object )] = array_shift( $object );
907 - }
908 -
909 - $objects = $o;
910 - }
911 - }
912 -
913 - return $objects;
914 - }
915 -
916 - /**
917 - * Selects the the specified fields of the first matching record.
918 - * Field names get prefixed.
919 - *
920 - * @since 1.20
921 - *
922 - * @param array|string|null $fields
923 - * @param array $conditions
924 - * @param array $options
925 - *
926 - * @return DBObject|bool False on failure
927 - */
928 - public static function selectRow( $fields = null, array $conditions = array(), array $options = array() ) {
929 - $options['LIMIT'] = 1;
930 -
931 - $objects = static::select( $fields, $conditions, $options );
932 -
933 - return count( $objects ) > 0 ? $objects[0] : false;
934 - }
935 -
936 - /**
937 - * Selects the the specified fields of the first record matching the provided
938 - * conditions and returns it as an associative array, or false when nothing matches.
939 - * This method makes use of selectFields and expects the same parameters and
940 - * returns the same results (if there are any, if there are none, this method returns false).
941 - * @see DBDataObject::selectFields
942 - *
943 - * @since 1.20
944 - *
945 - * @param array|string|null $fields
946 - * @param array $conditions
947 - * @param array $options
948 - * @param boolean $collapse Set to false to always return each result row as associative array.
949 - *
950 - * @return mixed|array|bool False on failure
951 - */
952 - public static function selectFieldsRow( $fields = null, array $conditions = array(), array $options = array(), $collapse = true ) {
953 - $options['LIMIT'] = 1;
954 -
955 - $objects = static::selectFields( $fields, $conditions, $options, $collapse );
956 -
957 - return count( $objects ) > 0 ? $objects[0] : false;
958 - }
959 -
960 - /**
961 - * Returns if there is at least one record matching the provided conditions.
962 - * Condition field names get prefixed.
963 - *
964 - * @since 1.20
965 - *
966 - * @param array $conditions
967 - *
968 - * @return boolean
969 - */
970 - public static function has( array $conditions = array() ) {
971 - return static::selectRow( array( 'id' ), $conditions ) !== false;
972 - }
973 -
974 - /**
975 - * Returns the amount of matching records.
976 - * Condition field names get prefixed.
977 - *
978 - * @since 1.20
979 - *
980 - * @param array $conditions
981 - * @param array $options
982 - *
983 - * @return integer
984 - */
985 - public static function count( array $conditions = array(), array $options = array() ) {
986 - $res = static::rawSelectRow(
987 - array( 'COUNT(*) AS rowcount' ),
988 - static::getPrefixedValues( $conditions ),
989 - $options
990 - );
991 -
992 - return $res->rowcount;
993 - }
994 -
995 - /**
996 - * Selects the the specified fields of the records matching the provided
997623 * conditions. Field names do NOT get prefixed.
998624 *
999625 * @since 1.20
@@ -1016,102 +642,17 @@
1017643 }
1018644
1019645 /**
1020 - * Update the records matching the provided conditions by
1021 - * setting the fields that are keys in the $values param to
1022 - * their corresponding values.
1023 - *
1024 - * @since 1.20
1025 - *
1026 - * @param array $values
1027 - * @param array $conditions
1028 - *
1029 - * @return boolean Success indicator
1030 - */
1031 - public static function update( array $values, array $conditions = array() ) {
1032 - $dbw = wfGetDB( DB_MASTER );
1033 -
1034 - return $dbw->update(
1035 - static::getDBTable(),
1036 - static::getPrefixedValues( $values ),
1037 - static::getPrefixedValues( $conditions ),
1038 - __METHOD__
1039 - );
1040 - }
1041 -
1042 - /**
1043646 * Return the names of the fields.
1044647 *
1045648 * @since 1.20
1046649 *
1047650 * @return array
1048651 */
1049 - public static function getFieldNames() {
1050 - return array_keys( static::getFieldTypes() );
 652+ public function getFieldNames() {
 653+ return array_keys( $this->table->getFieldTypes() );
1051654 }
1052655
1053656 /**
1054 - * Returns an array with the fields and their descriptions.
1055 - *
1056 - * field name => field description
1057 - *
1058 - * @since 1.20
1059 - *
1060 - * @return array
1061 - */
1062 - public static function getFieldDescriptions() {
1063 - return array();
1064 - }
1065 -
1066 - /**
1067 - * Get API parameters for the fields supported by this object.
1068 - *
1069 - * @since 1.20
1070 - *
1071 - * @param boolean $requireParams
1072 - * @param boolean $setDefaults
1073 - *
1074 - * @return array
1075 - */
1076 - public static function getAPIParams( $requireParams = false, $setDefaults = false ) {
1077 - $typeMap = array(
1078 - 'id' => 'integer',
1079 - 'int' => 'integer',
1080 - 'float' => 'NULL',
1081 - 'str' => 'string',
1082 - 'bool' => 'integer',
1083 - 'array' => 'string',
1084 - 'blob' => 'string',
1085 - );
1086 -
1087 - $params = array();
1088 - $defaults = static::getDefaults();
1089 -
1090 - foreach ( static::getFieldTypes() as $field => $type ) {
1091 - if ( $field == 'id' ) {
1092 - continue;
1093 - }
1094 -
1095 - $hasDefault = array_key_exists( $field, $defaults );
1096 -
1097 - $params[$field] = array(
1098 - ApiBase::PARAM_TYPE => $typeMap[$type],
1099 - ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault
1100 - );
1101 -
1102 - if ( $type == 'array' ) {
1103 - $params[$field][ApiBase::PARAM_ISMULTI] = true;
1104 - }
1105 -
1106 - if ( $setDefaults && $hasDefault ) {
1107 - $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
1108 - $params[$field][ApiBase::PARAM_DFLT] = $default;
1109 - }
1110 - }
1111 -
1112 - return $params;
1113 - }
1114 -
1115 - /**
1116657 * Computes and updates the values of the summary fields.
1117658 *
1118659 * @since 1.20
@@ -1123,26 +664,6 @@
1124665 }
1125666
1126667 /**
1127 - * Computes the values of the summary fields of the objects matching the provided conditions.
1128 - *
1129 - * @since 1.20
1130 - *
1131 - * @param array|string|null $summaryFields
1132 - * @param array $conditions
1133 - */
1134 - public static function updateSummaryFields( $summaryFields = null, array $conditions = array() ) {
1135 - self::setReadDb( DB_MASTER );
1136 -
1137 - foreach ( self::select( null, $conditions ) as /* DBDataObject */ $item ) {
1138 - $item->loadSummaryFields( $summaryFields );
1139 - $item->setSummaryMode( true );
1140 - $item->saveExisting();
1141 - }
1142 -
1143 - self::setReadDb( DB_SLAVE );
1144 - }
1145 -
1146 - /**
1147668 * Sets the value for the @see $updateSummaries field.
1148669 *
1149670 * @since 1.20
@@ -1185,5 +706,52 @@
1186707
1187708 return false;
1188709 }
 710+
 711+ protected function getDBTable() {
 712+ return $this->table->getDBTable();
 713+ }
 714+
 715+ /**
 716+ * Get an array with fields from a database result,
 717+ * that can be fed directly to the constructor or
 718+ * to setFields.
 719+ *
 720+ * @since 1.20
 721+ *
 722+ * @param object $result
 723+ *
 724+ * @return array
 725+ */
 726+ public function getFieldsFromDBResult( $result ) {
 727+ $result = (array)$result;
 728+ return array_combine(
 729+ $this->unprefixFieldNames( array_keys( $result ) ),
 730+ array_values( $result )
 731+ );
 732+ }
 733+
 734+ /**
 735+ * Get a new instance of the class from a database result.
 736+ *
 737+ * @since 1.20
 738+ *
 739+ * @param stdClass $result
 740+ *
 741+ * @return DBDataObject
 742+ */
 743+ public function newFromDBResult( stdClass $result ) {
 744+ return $this->newFromArray( $this->getFieldsFromDBResult( $result ) );
 745+ }
 746+
 747+ /**
 748+ * Returns the table this DBDataObject is a row in.
 749+ *
 750+ * @since 1.20
 751+ *
 752+ * @return DBTable
 753+ */
 754+ public function getTable() {
 755+ return $this->table;
 756+ }
1189757
1190758 }
Index: trunk/phase3/includes/AutoLoader.php
@@ -51,6 +51,7 @@
5252 'CookieJar' => 'includes/Cookie.php',
5353 'CurlHttpRequest' => 'includes/HttpFunctions.php',
5454 'DBDataObject' => 'includes/DBDataObject.php',
 55+ 'DBTable' => 'includes/DBTable.php',
5556 'DeferrableUpdate' => 'includes/DeferredUpdates.php',
5657 'DeferredUpdates' => 'includes/DeferredUpdates.php',
5758 'DeprecatedGlobal' => 'includes/DeprecatedGlobal.php',
Index: trunk/phase3/includes/DBTable.php
@@ -0,0 +1,522 @@
 2+<?php
 3+
 4+/**
 5+ * Abstract base class for representing a single database table.
 6+ *
 7+ * @since 1.20
 8+ *
 9+ * @file DBTable.php
 10+ *
 11+ * @licence GNU GPL v2 or later
 12+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 13+ */
 14+abstract class DBTable {
 15+
 16+ /**
 17+ * Returns the name of the database table objects of this type are stored in.
 18+ *
 19+ * @since 1.20
 20+ *
 21+ * @return string
 22+ */
 23+ public abstract function getDBTable();
 24+
 25+ /**
 26+ * Returns the name of a DBDataObject deriving class that
 27+ * represents single rows in this table.
 28+ *
 29+ * @since 1.20
 30+ *
 31+ * @return string
 32+ */
 33+ protected abstract function getDataObjectClass();
 34+
 35+ /**
 36+ * Gets the db field prefix.
 37+ *
 38+ * @since 1.20
 39+ *
 40+ * @return string
 41+ */
 42+ protected abstract function getFieldPrefix();
 43+
 44+ /**
 45+ * Returns an array with the fields and their types this object contains.
 46+ * This corresponds directly to the fields in the database, without prefix.
 47+ *
 48+ * field name => type
 49+ *
 50+ * Allowed types:
 51+ * * id
 52+ * * str
 53+ * * int
 54+ * * float
 55+ * * bool
 56+ * * array
 57+ *
 58+ * @since 1.20
 59+ *
 60+ * @return array
 61+ */
 62+ public abstract function getFieldTypes();
 63+
 64+ /**
 65+ * The database connection to use for read operations.
 66+ * Can be changed via @see setReadDb.
 67+ *
 68+ * @since 1.20
 69+ * @var integer DB_ enum
 70+ */
 71+ protected $readDb = DB_SLAVE;
 72+
 73+ /**
 74+ * Returns a list of default field values.
 75+ * field name => field value
 76+ *
 77+ * @since 1.20
 78+ *
 79+ * @return array
 80+ */
 81+ public function getDefaults() {
 82+ return array();
 83+ }
 84+
 85+ /**
 86+ * Returns a list of the summary fields.
 87+ * These are fields that cache computed values, such as the amount of linked objects of $type.
 88+ * This is relevant as one might not want to do actions such as log changes when these get updated.
 89+ *
 90+ * @since 1.20
 91+ *
 92+ * @return array
 93+ */
 94+ public function getSummaryFields() {
 95+ return array();
 96+ }
 97+
 98+ /**
 99+ * Selects the the specified fields of the records matching the provided
 100+ * conditions and returns them as DBDataObject. Field names get prefixed.
 101+ *
 102+ * @since 1.20
 103+ *
 104+ * @param array|string|null $fields
 105+ * @param array $conditions
 106+ * @param array $options
 107+ *
 108+ * @return array of self
 109+ */
 110+ public function select( $fields = null, array $conditions = array(), array $options = array() ) {
 111+ $result = $this->selectFields( $fields, $conditions, $options, false );
 112+
 113+ $objects = array();
 114+
 115+ foreach ( $result as $record ) {
 116+ $objects[] = $this->newFromArray( $record );
 117+ }
 118+
 119+ return $objects;
 120+ }
 121+
 122+ /**
 123+ * Selects the the specified fields of the records matching the provided
 124+ * conditions and returns them as associative arrays.
 125+ * Provided field names get prefixed.
 126+ * Returned field names will not have a prefix.
 127+ *
 128+ * When $collapse is true:
 129+ * If one field is selected, each item in the result array will be this field.
 130+ * If two fields are selected, each item in the result array will have as key
 131+ * the first field and as value the second field.
 132+ * If more then two fields are selected, each item will be an associative array.
 133+ *
 134+ * @since 1.20
 135+ *
 136+ * @param array|string|null $fields
 137+ * @param array $conditions
 138+ * @param array $options
 139+ * @param boolean $collapse Set to false to always return each result row as associative array.
 140+ *
 141+ * @return array of array
 142+ */
 143+ public function selectFields( $fields = null, array $conditions = array(), array $options = array(), $collapse = true ) {
 144+ if ( is_null( $fields ) ) {
 145+ $fields = array_keys( $this->getFieldTypes() );
 146+ }
 147+ else {
 148+ $fields = (array)$fields;
 149+ }
 150+
 151+ $dbr = wfGetDB( $this->getReadDb() );
 152+ $result = $dbr->select(
 153+ $this->getDBTable(),
 154+ $this->getPrefixedFields( $fields ),
 155+ $this->getPrefixedValues( $conditions ),
 156+ __METHOD__,
 157+ $options
 158+ );
 159+
 160+ $objects = array();
 161+
 162+ foreach ( $result as $record ) {
 163+ $objects[] = $this->getFieldsFromDBResult( $record );
 164+ }
 165+
 166+ if ( $collapse ) {
 167+ if ( count( $fields ) === 1 ) {
 168+ $objects = array_map( 'array_shift', $objects );
 169+ }
 170+ elseif ( count( $fields ) === 2 ) {
 171+ $o = array();
 172+
 173+ foreach ( $objects as $object ) {
 174+ $o[array_shift( $object )] = array_shift( $object );
 175+ }
 176+
 177+ $objects = $o;
 178+ }
 179+ }
 180+
 181+ return $objects;
 182+ }
 183+
 184+ /**
 185+ * Selects the the specified fields of the first matching record.
 186+ * Field names get prefixed.
 187+ *
 188+ * @since 1.20
 189+ *
 190+ * @param array|string|null $fields
 191+ * @param array $conditions
 192+ * @param array $options
 193+ *
 194+ * @return DBObject|bool False on failure
 195+ */
 196+ public function selectRow( $fields = null, array $conditions = array(), array $options = array() ) {
 197+ $options['LIMIT'] = 1;
 198+
 199+ $objects = $this->select( $fields, $conditions, $options );
 200+
 201+ return count( $objects ) > 0 ? $objects[0] : false;
 202+ }
 203+
 204+ /**
 205+ * Selects the the specified fields of the first record matching the provided
 206+ * conditions and returns it as an associative array, or false when nothing matches.
 207+ * This method makes use of selectFields and expects the same parameters and
 208+ * returns the same results (if there are any, if there are none, this method returns false).
 209+ * @see DBDataObject::selectFields
 210+ *
 211+ * @since 1.20
 212+ *
 213+ * @param array|string|null $fields
 214+ * @param array $conditions
 215+ * @param array $options
 216+ * @param boolean $collapse Set to false to always return each result row as associative array.
 217+ *
 218+ * @return mixed|array|bool False on failure
 219+ */
 220+ public function selectFieldsRow( $fields = null, array $conditions = array(), array $options = array(), $collapse = true ) {
 221+ $options['LIMIT'] = 1;
 222+
 223+ $objects = $this->selectFields( $fields, $conditions, $options, $collapse );
 224+
 225+ return count( $objects ) > 0 ? $objects[0] : false;
 226+ }
 227+
 228+ /**
 229+ * Returns if there is at least one record matching the provided conditions.
 230+ * Condition field names get prefixed.
 231+ *
 232+ * @since 1.20
 233+ *
 234+ * @param array $conditions
 235+ *
 236+ * @return boolean
 237+ */
 238+ public function has( array $conditions = array() ) {
 239+ return $this->selectRow( array( 'id' ), $conditions ) !== false;
 240+ }
 241+
 242+ /**
 243+ * Returns the amount of matching records.
 244+ * Condition field names get prefixed.
 245+ *
 246+ * @since 1.20
 247+ *
 248+ * @param array $conditions
 249+ * @param array $options
 250+ *
 251+ * @return integer
 252+ */
 253+ public function count( array $conditions = array(), array $options = array() ) {
 254+ $res = $this->rawSelectRow(
 255+ array( 'COUNT(*) AS rowcount' ),
 256+ $this->getPrefixedValues( $conditions ),
 257+ $options
 258+ );
 259+
 260+ return $res->rowcount;
 261+ }
 262+
 263+ /**
 264+ * Removes the object from the database.
 265+ *
 266+ * @since 1.20
 267+ *
 268+ * @param array $conditions
 269+ *
 270+ * @return boolean Success indicator
 271+ */
 272+ public function delete( array $conditions ) {
 273+ return wfGetDB( DB_MASTER )->delete(
 274+ $this->getDBTable(),
 275+ $this->getPrefixedValues( $conditions )
 276+ );
 277+ }
 278+
 279+ /**
 280+ * Get API parameters for the fields supported by this object.
 281+ *
 282+ * @since 1.20
 283+ *
 284+ * @param boolean $requireParams
 285+ * @param boolean $setDefaults
 286+ *
 287+ * @return array
 288+ */
 289+ public function getAPIParams( $requireParams = false, $setDefaults = false ) {
 290+ $typeMap = array(
 291+ 'id' => 'integer',
 292+ 'int' => 'integer',
 293+ 'float' => 'NULL',
 294+ 'str' => 'string',
 295+ 'bool' => 'integer',
 296+ 'array' => 'string',
 297+ 'blob' => 'string',
 298+ );
 299+
 300+ $params = array();
 301+ $defaults = $this->getDefaults();
 302+
 303+ foreach ( $this->getFieldTypes() as $field => $type ) {
 304+ if ( $field == 'id' ) {
 305+ continue;
 306+ }
 307+
 308+ $hasDefault = array_key_exists( $field, $defaults );
 309+
 310+ $params[$field] = array(
 311+ ApiBase::PARAM_TYPE => $typeMap[$type],
 312+ ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault
 313+ );
 314+
 315+ if ( $type == 'array' ) {
 316+ $params[$field][ApiBase::PARAM_ISMULTI] = true;
 317+ }
 318+
 319+ if ( $setDefaults && $hasDefault ) {
 320+ $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
 321+ $params[$field][ApiBase::PARAM_DFLT] = $default;
 322+ }
 323+ }
 324+
 325+ return $params;
 326+ }
 327+
 328+ /**
 329+ * Returns an array with the fields and their descriptions.
 330+ *
 331+ * field name => field description
 332+ *
 333+ * @since 1.20
 334+ *
 335+ * @return array
 336+ */
 337+ public function getFieldDescriptions() {
 338+ return array();
 339+ }
 340+
 341+ /**
 342+ * Get the database type used for read operations.
 343+ *
 344+ * @since 1.20
 345+ *
 346+ * @return integer DB_ enum
 347+ */
 348+ public function getReadDb() {
 349+ return $this->readDb;
 350+ }
 351+
 352+ /**
 353+ * Set the database type to use for read operations.
 354+ *
 355+ * @param integer $db
 356+ *
 357+ * @since 1.20
 358+ */
 359+ public function setReadDb( $db ) {
 360+ $this->readDb = $db;
 361+ }
 362+
 363+ /**
 364+ * Update the records matching the provided conditions by
 365+ * setting the fields that are keys in the $values param to
 366+ * their corresponding values.
 367+ *
 368+ * @since 1.20
 369+ *
 370+ * @param array $values
 371+ * @param array $conditions
 372+ *
 373+ * @return boolean Success indicator
 374+ */
 375+ public function update( array $values, array $conditions = array() ) {
 376+ $dbw = wfGetDB( DB_MASTER );
 377+
 378+ return $dbw->update(
 379+ $this->getDBTable(),
 380+ $this->getPrefixedValues( $values ),
 381+ $this->getPrefixedValues( $conditions ),
 382+ __METHOD__
 383+ );
 384+ }
 385+
 386+ /**
 387+ * Computes the values of the summary fields of the objects matching the provided conditions.
 388+ *
 389+ * @since 1.20
 390+ *
 391+ * @param array|string|null $summaryFields
 392+ * @param array $conditions
 393+ */
 394+ public function updateSummaryFields( $summaryFields = null, array $conditions = array() ) {
 395+ $this->setReadDb( DB_MASTER );
 396+
 397+ foreach ( $this->select( null, $conditions ) as /* DBDataObject */ $item ) {
 398+ $item->loadSummaryFields( $summaryFields );
 399+ $item->setSummaryMode( true );
 400+ $item->saveExisting();
 401+ }
 402+
 403+ $this->setReadDb( DB_SLAVE );
 404+ }
 405+
 406+ /**
 407+ * Takes in an associative array with field names as keys and
 408+ * their values as value. The field names are prefixed with the
 409+ * db field prefix.
 410+ *
 411+ * Field names can also be provided as an array with as first element a table name, such as
 412+ * $conditions = array(
 413+ * array( array( 'tablename', 'fieldname' ), $value ),
 414+ * );
 415+ *
 416+ * @since 1.20
 417+ *
 418+ * @param array $values
 419+ *
 420+ * @return array
 421+ */
 422+ public function getPrefixedValues( array $values ) {
 423+ $prefixedValues = array();
 424+
 425+ foreach ( $values as $field => $value ) {
 426+ if ( is_integer( $field ) ) {
 427+ if ( is_array( $value ) ) {
 428+ $field = $value[0];
 429+ $value = $value[1];
 430+ }
 431+ else {
 432+ $value = explode( ' ', $value, 2 );
 433+ $value[0] = $this->getPrefixedField( $value[0] );
 434+ $prefixedValues[] = implode( ' ', $value );
 435+ continue;
 436+ }
 437+ }
 438+
 439+ $prefixedValues[$this->getPrefixedField( $field )] = $value;
 440+ }
 441+
 442+ return $prefixedValues;
 443+ }
 444+
 445+ /**
 446+ * Takes in a field or array of fields and returns an
 447+ * array with their prefixed versions, ready for db usage.
 448+ *
 449+ * @since 1.20
 450+ *
 451+ * @param array|string $fields
 452+ *
 453+ * @return array
 454+ */
 455+ public function getPrefixedFields( array $fields ) {
 456+ foreach ( $fields as &$field ) {
 457+ $field = $this->getPrefixedField( $field );
 458+ }
 459+
 460+ return $fields;
 461+ }
 462+
 463+ /**
 464+ * Takes in a field and returns an it's prefixed version, ready for db usage.
 465+ *
 466+ * @since 1.20
 467+ *
 468+ * @param string|array $field
 469+ *
 470+ * @return string
 471+ */
 472+ public function getPrefixedField( $field ) {
 473+ return $this->getFieldPrefix() . $field;
 474+ }
 475+
 476+ /**
 477+ * Takes an array of field names with prefix and returns the unprefixed equivalent.
 478+ *
 479+ * @since 1.20
 480+ *
 481+ * @param array $fieldNames
 482+ *
 483+ * @return array
 484+ */
 485+ public function unprefixFieldNames( array $fieldNames ) {
 486+ return array_map( '$this->unprefixFieldName', $fieldNames );
 487+ }
 488+
 489+ /**
 490+ * Takes a field name with prefix and returns the unprefixed equivalent.
 491+ *
 492+ * @since 1.20
 493+ *
 494+ * @param string $fieldName
 495+ *
 496+ * @return string
 497+ */
 498+ public function unprefixFieldName( $fieldName ) {
 499+ return substr( $fieldName, strlen( $this->getFieldPrefix() ) );
 500+ }
 501+
 502+ public function __construct() {
 503+
 504+ }
 505+
 506+ /**
 507+ * Get an instance of this class.
 508+ *
 509+ * @since 1.20
 510+ *
 511+ * @return DBtable
 512+ */
 513+ public static function &singleton() {
 514+ static $instance;
 515+
 516+ if ( !isset( $instance ) ) {
 517+ $instance = new static;
 518+ }
 519+
 520+ return $instance;
 521+ }
 522+
 523+}
Property changes on: trunk/phase3/includes/DBTable.php
___________________________________________________________________
Added: svn:eol-style
1524 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r111469follow up to r111468jeroendedauw18:12, 14 February 2012
r111490follow up to r111468 - moved a bunch of methods from DBDataObject to DBTable ...jeroendedauw21:16, 14 February 2012
r111498follow up to r111468 - fixed various issues caused by refactoringjeroendedauw21:42, 14 February 2012
r111551Follow-up r111468, there were some changes left.platonides16:04, 15 February 2012
r111567follow up to r111468 - put in compatibility for php 5.2 using debug_backtrace...jeroendedauw19:39, 15 February 2012

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r111264adding DBDataObject class after having some people review it and posting on t...jeroendedauw21:34, 11 February 2012

Comments

#Comment by Platonides (talk | contribs)   16:15, 15 February 2012
function &singleton()

This is PHP 5, that reference would be only needed if you wanted to make $instance something else.

$instance = new static;

This line still makes it require PHP 5.3.

Use $this->className = new EPOrgs ?

#Comment by Jeroen De Dauw (talk | contribs)   16:56, 15 February 2012

ref removed in r111558

> Use $this->className = new EPOrgs ?

Man, this is why we should switch to PHP 5.3. It's flipping ridiculous to have to put such boilerplate code in EVERY subclass >_> And I really do not want to crappify the EducationProgram code which can use 5.3 anyway by putting that in. So what about having this field be optional, and use it when it's set, and when it's not, use the static keyword?

#Comment by Jeroen De Dauw (talk | contribs)   19:40, 15 February 2012

Got rid of the static keyword and am now using get_called_class on 5.3 or later installs and falling back to debug_backtrace hack on 5.2.x.

#Comment by Platonides (talk | contribs)   22:59, 15 February 2012

Much appreciated.

Status & tagging log