Index: trunk/extensions/Tasks/categoryfinder.php |
— | — | @@ -1,186 +0,0 @@ |
2 | | -<?php |
3 | | -/* |
4 | | -The "Categoryfinder" class takes a list of articles, creates an internal representation of all their parent |
5 | | -categories (as well as parents of parents etc.). From this representation, it determines which of these articles |
6 | | -are in one or all of a given subset of categories. |
7 | | - |
8 | | -Example use : |
9 | | - |
10 | | - # Determines wether the article with the page_id 12345 is in both |
11 | | - # "Category 1" and "Category 2" or their subcategories, respectively |
12 | | - |
13 | | - $cf = new Categoryfinder ; |
14 | | - $cf->seed ( |
15 | | - array ( 12345 ) , |
16 | | - array ( "Category 1","Category 2" ) , |
17 | | - "AND" |
18 | | - ) ; |
19 | | - $a = $cf->run() ; |
20 | | - print implode ( "," , $a ) ; |
21 | | - |
22 | | -*/ |
23 | | - |
24 | | - |
25 | | -if( !defined( 'MEDIAWIKI' ) ) die(); |
26 | | - |
27 | | -class Categoryfinder { |
28 | | - |
29 | | - var $articles = array () ; # The original article IDs passed to the seed function |
30 | | - var $deadend = array () ; # Array of DBKEY category names for categories that don't have a page |
31 | | - var $parents = array () ; # Array of [ID => array()] |
32 | | - var $next = array () ; # Array of article/category IDs |
33 | | - var $targets = array () ; # Array of DBKEY category names |
34 | | - var $name2id = array () ; |
35 | | - var $mode ; # "AND" or "OR" |
36 | | - var $dbr ; # Read-DB slave |
37 | | - |
38 | | - /** |
39 | | - * Constructor (currently empty). |
40 | | - */ |
41 | | - function __construct () { |
42 | | - } |
43 | | - |
44 | | - /** |
45 | | - * Initializes the instance. Do this prior to calling run(). |
46 | | - @param $article_ids Array of article IDs |
47 | | - */ |
48 | | - function seed ( $article_ids , $categories , $mode = "AND" ) { |
49 | | - $this->articles = $article_ids ; |
50 | | - $this->next = $article_ids ; |
51 | | - $this->mode = $mode ; |
52 | | - |
53 | | - # Set the list of target categories; convert them to DBKEY form first |
54 | | - $this->targets = array () ; |
55 | | - foreach ( $categories AS $c ) { |
56 | | - $ct = Title::newFromText ( $c , NS_CATEGORY ) ; |
57 | | - $c = $ct->getDBkey () ; |
58 | | - $this->targets[$c] = $c ; |
59 | | - } |
60 | | - } |
61 | | - |
62 | | - /** |
63 | | - * Iterates through the parent tree starting with the seed values, |
64 | | - * then checks the articles if they match the conditions |
65 | | - @return array of page_ids (those given to seed() that match the conditions) |
66 | | - */ |
67 | | - function run () { |
68 | | - $this->dbr = wfGetDB( DB_SLAVE ); |
69 | | -# $iterations = 0 ; |
70 | | - while ( count ( $this->next ) > 0 ) { |
71 | | - $this->scan_next_layer () ; |
72 | | -# $iterations++ ; |
73 | | - } |
74 | | -# print "<p>{$iterations} iterations</p>" ; |
75 | | - |
76 | | - # Now check if this applies to the individual articles |
77 | | - $ret = array () ; |
78 | | - foreach ( $this->articles AS $article ) { |
79 | | - $conds = $this->targets ; |
80 | | - if ( $this->check ( $article , $conds ) ) { |
81 | | - # Matches the conditions |
82 | | - $ret[] = $article ; |
83 | | - } |
84 | | - } |
85 | | - return $ret ; |
86 | | - } |
87 | | - |
88 | | - /** |
89 | | - * This functions recurses through the parent representation, trying to match the conditions |
90 | | - @param $id The article/category to check |
91 | | - @param $conds The array of categories to match |
92 | | - @return bool Does this match the conditions? |
93 | | - */ |
94 | | - function check ( $id , &$conds ) { |
95 | | - # Shortcut (runtime paranoia): No contitions=all matched |
96 | | - if ( count ( $conds ) == 0 ) return true ; |
97 | | - |
98 | | - # iterate through the parents |
99 | | - foreach ( $this->parents[$id] AS $p ) { |
100 | | - $pname = $p->cl_to ; |
101 | | - |
102 | | - # Is this a condition? |
103 | | - if ( isset ( $conds[$pname] ) ) { |
104 | | - # This key is in the category list! |
105 | | - if ( $this->mode == "OR" ) { |
106 | | - # One found, that's enough! |
107 | | - $conds = array () ; |
108 | | - return true ; |
109 | | - } else { |
110 | | - # Assuming "AND" as default |
111 | | - unset ( $conds[$pname] ) ; |
112 | | - if ( count ( $conds ) == 0 ) { |
113 | | - # All conditions met, done |
114 | | - return true ; |
115 | | - } |
116 | | - } |
117 | | - } |
118 | | - |
119 | | - # Not done yet, try sub-parents |
120 | | - if ( !isset ( $this->name2id[$pname] ) ) { |
121 | | - # No sub-parent |
122 | | - continue ; |
123 | | - } |
124 | | - $done = $this->check ( $this->name2id[$pname] , $conds ) ; |
125 | | - if ( $done OR count ( $conds ) == 0 ) { |
126 | | - # Subparents have done it! |
127 | | - return true ; |
128 | | - } |
129 | | - } |
130 | | - return false ; |
131 | | - } |
132 | | - |
133 | | - /** |
134 | | - * Scans a "parent layer" of the articles/categories in $this->next |
135 | | - */ |
136 | | - function scan_next_layer () { |
137 | | - |
138 | | - # Find all parents of the article currently in $this->next |
139 | | - $layer = array () ; |
140 | | - $res = $this->dbr->select( |
141 | | - /* FROM */ 'categorylinks', |
142 | | - /* SELECT */ '*', |
143 | | - /* WHERE */ array( 'cl_from' => $this->next ) |
144 | | - ); |
145 | | - while ( $o = $this->dbr->fetchObject( $res ) ) { |
146 | | - $k = $o->cl_to ; |
147 | | - |
148 | | - # Update parent tree |
149 | | - if ( !isset ( $this->parents[$o->cl_from] ) ) { |
150 | | - $this->parents[$o->cl_from] = array () ; |
151 | | - } |
152 | | - $this->parents[$o->cl_from][$k] = $o ; |
153 | | - |
154 | | - # Ignore those we already have |
155 | | - if ( in_array ( $k , $this->deadend ) ) continue ; |
156 | | - if ( isset ( $this->name2id[$k] ) ) continue ; |
157 | | - |
158 | | - # Hey, new category! |
159 | | - $layer[$k] = $k ; |
160 | | - } |
161 | | - $this->dbr->freeResult( $res ) ; |
162 | | - |
163 | | - $this->next = array() ; |
164 | | - |
165 | | - # Find the IDs of all category pages in $layer, if they exist |
166 | | - $res = $this->dbr->select( |
167 | | - /* FROM */ 'page', |
168 | | - /* SELECT */ 'page_id,page_title', |
169 | | - /* WHERE */ array( 'page_namespace' => NS_CATEGORY , 'page_title' => $layer ) |
170 | | - ); |
171 | | - while ( $o = $this->dbr->fetchObject( $res ) ) { |
172 | | - $id = $o->page_id ; |
173 | | - $name = $o->page_title ; |
174 | | - $this->name2id[$name] = $id ; |
175 | | - $this->next[] = $id ; |
176 | | - unset ( $layer[$name] ) ; |
177 | | - } |
178 | | - $this->dbr->freeResult( $res ) ; |
179 | | - |
180 | | - # Mark dead ends |
181 | | - foreach ( $layer AS $v ) { |
182 | | - $this->deadend[$v] = $v ; |
183 | | - } |
184 | | - } |
185 | | - |
186 | | -} # END OF CLASS "Categoryfinder" |
187 | | - |
Index: trunk/extensions/Tasks/Tasks.php |
— | — | @@ -17,9 +17,6 @@ |
18 | 18 | |
19 | 19 | if( !defined( 'MEDIAWIKI' ) ) die(); |
20 | 20 | |
21 | | -// FIXME: use lazy loading |
22 | | -require_once ( "categoryfinder.php" ) ; |
23 | | - |
24 | 21 | /** Default path to the stylesheet */ |
25 | 22 | global $wgScriptPath ; |
26 | 23 | if( !defined( 'TASKS_CSS' ) ) define('TASKS_CSS', $wgScriptPath.'/extensions/Tasks/tasks.css' ); |