qa-xml-sitemap.php 8.12 KB
Newer Older
Gideon Greenspan committed
1 2 3 4 5 6 7
<?php

/*
	Question2Answer (c) Gideon Greenspan

	http://www.question2answer.org/

8

Gideon Greenspan committed
9 10 11 12 13 14 15 16 17
	File: qa-plugin/xml-sitemap/qa-xml-sitemap.php
	Version: See define()s at top of qa-include/qa-base.php
	Description: Page module class for XML sitemap plugin


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
18

Gideon Greenspan committed
19 20 21 22 23 24 25 26 27
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/

	class qa_xml_sitemap {
28

29 30
		private $directory;
		private $urltoroot;
31

32
		public function load_module($directory, $urltoroot)
Gideon Greenspan committed
33 34 35 36 37
		{
			$this->directory=$directory;
			$this->urltoroot=$urltoroot;
		}

38

39
		public function option_default($option)
Gideon Greenspan committed
40 41 42 43 44 45 46 47 48 49 50
		{
			switch ($option) {
				case 'xml_sitemap_show_questions':
				case 'xml_sitemap_show_users':
				case 'xml_sitemap_show_tag_qs':
				case 'xml_sitemap_show_category_qs':
				case 'xml_sitemap_show_categories':
					return true;
					break;
			}
		}
51 52


53
		public function admin_form()
Gideon Greenspan committed
54 55
		{
			require_once QA_INCLUDE_DIR.'qa-util-sort.php';
56

Gideon Greenspan committed
57
			$saved=false;
58

Gideon Greenspan committed
59 60
			if (qa_clicked('xml_sitemap_save_button')) {
				qa_opt('xml_sitemap_show_questions', (int)qa_post_text('xml_sitemap_show_questions_field'));
61

Gideon Greenspan committed
62 63
				if (!QA_FINAL_EXTERNAL_USERS)
					qa_opt('xml_sitemap_show_users', (int)qa_post_text('xml_sitemap_show_users_field'));
64

Gideon Greenspan committed
65 66
				if (qa_using_tags())
					qa_opt('xml_sitemap_show_tag_qs', (int)qa_post_text('xml_sitemap_show_tag_qs_field'));
67

Gideon Greenspan committed
68 69 70 71
				if (qa_using_categories()) {
					qa_opt('xml_sitemap_show_category_qs', (int)qa_post_text('xml_sitemap_show_category_qs_field'));
					qa_opt('xml_sitemap_show_categories', (int)qa_post_text('xml_sitemap_show_categories_field'));
				}
72

Gideon Greenspan committed
73 74
				$saved=true;
			}
75

Gideon Greenspan committed
76 77 78 79 80 81 82 83
			$form=array(
				'ok' => $saved ? 'XML sitemap settings saved' : null,

				'fields' => array(
					'questions' => array(
						'label' => 'Include question pages',
						'type' => 'checkbox',
						'value' => (int)qa_opt('xml_sitemap_show_questions'),
Gideon Greenspan committed
84
						'tags' => 'name="xml_sitemap_show_questions_field"',
Gideon Greenspan committed
85 86
					),
				),
87

Gideon Greenspan committed
88 89 90
				'buttons' => array(
					array(
						'label' => 'Save Changes',
Gideon Greenspan committed
91
						'tags' => 'name="xml_sitemap_save_button"',
Gideon Greenspan committed
92 93 94
					),
				),
			);
95

Gideon Greenspan committed
96 97 98 99 100
			if (!QA_FINAL_EXTERNAL_USERS)
				$form['fields']['users']=array(
					'label' => 'Include user pages',
					'type' => 'checkbox',
					'value' => (int)qa_opt('xml_sitemap_show_users'),
Gideon Greenspan committed
101
					'tags' => 'name="xml_sitemap_show_users_field"',
Gideon Greenspan committed
102
				);
103

Gideon Greenspan committed
104 105 106 107 108
			if (qa_using_tags())
				$form['fields']['tagqs']=array(
					'label' => 'Include question list for each tag',
					'type' => 'checkbox',
					'value' => (int)qa_opt('xml_sitemap_show_tag_qs'),
Gideon Greenspan committed
109
					'tags' => 'name="xml_sitemap_show_tag_qs_field"',
Gideon Greenspan committed
110 111 112 113 114 115 116
				);

			if (qa_using_categories()) {
				$form['fields']['categoryqs']=array(
					'label' => 'Include question list for each category',
					'type' => 'checkbox',
					'value' => (int)qa_opt('xml_sitemap_show_category_qs'),
Gideon Greenspan committed
117
					'tags' => 'name="xml_sitemap_show_category_qs_field"',
Gideon Greenspan committed
118 119 120 121 122 123
				);

				$form['fields']['categories']=array(
					'label' => 'Include category browser',
					'type' => 'checkbox',
					'value' => (int)qa_opt('xml_sitemap_show_categories'),
Gideon Greenspan committed
124
					'tags' => 'name="xml_sitemap_show_categories_field"',
Gideon Greenspan committed
125 126 127 128 129 130
				);
			}

			return $form;
		}

131

132
		public function suggest_requests()
133
		{
Gideon Greenspan committed
134 135 136 137 138 139 140 141 142
			return array(
				array(
					'title' => 'XML Sitemap',
					'request' => 'sitemap.xml',
					'nav' => null, // 'M'=main, 'F'=footer, 'B'=before main, 'O'=opposite main, null=none
				),
			);
		}

143

144
		public function match_request($request)
Gideon Greenspan committed
145 146 147 148
		{
			return ($request=='sitemap.xml');
		}

149

150
		public function process_request($request)
Gideon Greenspan committed
151 152 153 154
		{
			@ini_set('display_errors', 0); // we don't want to show PHP errors inside XML

			$siteurl=qa_opt('site_url');
155

Gideon Greenspan committed
156
			header('Content-type: text/xml; charset=utf-8');
157

Gideon Greenspan committed
158 159
			echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";
			echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n";
160

Gideon Greenspan committed
161 162

		//	Question pages
163

Gideon Greenspan committed
164 165 166 167
			if (qa_opt('xml_sitemap_show_questions')) {
				$hotstats=qa_db_read_one_assoc(qa_db_query_sub(
					"SELECT MIN(hotness) AS base, MAX(hotness)-MIN(hotness) AS spread FROM ^posts WHERE type='Q'"
				));
168

Gideon Greenspan committed
169
				$nextpostid=0;
170

Gideon Greenspan committed
171 172 173 174 175
				while (1) {
					$questions=qa_db_read_all_assoc(qa_db_query_sub(
						"SELECT postid, title, hotness FROM ^posts WHERE postid>=# AND type='Q' ORDER BY postid LIMIT 100",
						$nextpostid
					));
176

Gideon Greenspan committed
177 178
					if (!count($questions))
						break;
179

Gideon Greenspan committed
180 181
					foreach ($questions as $question) {
						$this->sitemap_output(qa_q_request($question['postid'], $question['title']),
Gideon Greenspan committed
182
							0.1+0.9*($question['hotness']-$hotstats['base'])/(1+$hotstats['spread']));
Gideon Greenspan committed
183 184 185 186
						$nextpostid=max($nextpostid, $question['postid']+1);
					}
				}
			}
187

Gideon Greenspan committed
188 189

		//	User pages
190

Gideon Greenspan committed
191 192
			if ((!QA_FINAL_EXTERNAL_USERS) && qa_opt('xml_sitemap_show_users')) {
				$nextuserid=0;
193

Gideon Greenspan committed
194 195 196 197 198
				while (1) {
					$users=qa_db_read_all_assoc(qa_db_query_sub(
						"SELECT userid, handle FROM ^users WHERE userid>=# ORDER BY userid LIMIT 100",
						$nextuserid
					));
199

Gideon Greenspan committed
200 201
					if (!count($users))
						break;
202

Gideon Greenspan committed
203 204 205 206 207 208
					foreach ($users as $user) {
						$this->sitemap_output('user/'.$user['handle'], 0.25);
						$nextuserid=max($nextuserid, $user['userid']+1);
					}
				}
			}
209

Gideon Greenspan committed
210 211

		//	Tag pages
212

Gideon Greenspan committed
213 214
			if (qa_using_tags() && qa_opt('xml_sitemap_show_tag_qs')) {
				$nextwordid=0;
215

Gideon Greenspan committed
216 217 218 219 220
				while (1) {
					$tagwords=qa_db_read_all_assoc(qa_db_query_sub(
						"SELECT wordid, word, tagcount FROM ^words WHERE wordid>=# AND tagcount>0 ORDER BY wordid LIMIT 100",
						$nextwordid
					));
221

Gideon Greenspan committed
222 223
					if (!count($tagwords))
						break;
224

Gideon Greenspan committed
225 226 227
					foreach ($tagwords as $tagword) {
						$this->sitemap_output('tag/'.$tagword['word'], 0.5/(1+(1/$tagword['tagcount']))); // priority between 0.25 and 0.5 depending on tag frequency
						$nextwordid=max($nextwordid, $tagword['wordid']+1);
228
					}
Gideon Greenspan committed
229 230
				}
			}
231 232


Gideon Greenspan committed
233
		//	Question list for each category
234

Gideon Greenspan committed
235 236
			if (qa_using_categories() && qa_opt('xml_sitemap_show_category_qs')) {
				$nextcategoryid=0;
237

Gideon Greenspan committed
238 239 240 241 242
				while (1) {
					$categories=qa_db_read_all_assoc(qa_db_query_sub(
						"SELECT categoryid, backpath FROM ^categories WHERE categoryid>=# AND qcount>0 ORDER BY categoryid LIMIT 2",
						$nextcategoryid
					));
243

Gideon Greenspan committed
244 245
					if (!count($categories))
						break;
246

Gideon Greenspan committed
247 248 249 250 251 252
					foreach ($categories as $category) {
						$this->sitemap_output('questions/'.implode('/', array_reverse(explode('/', $category['backpath']))), 0.5);
						$nextcategoryid=max($nextcategoryid, $category['categoryid']+1);
					}
				}
			}
253 254


Gideon Greenspan committed
255
		//	Pages in category browser
256

Gideon Greenspan committed
257 258
			if (qa_using_categories() && qa_opt('xml_sitemap_show_categories')) {
				$this->sitemap_output('categories', 0.5);
259

Gideon Greenspan committed
260
				$nextcategoryid=0;
261

Gideon Greenspan committed
262 263 264 265 266 267
				while (1) { // only find categories with a child
					$categories=qa_db_read_all_assoc(qa_db_query_sub(
						"SELECT parent.categoryid, parent.backpath FROM ^categories AS parent ".
						"JOIN ^categories AS child ON child.parentid=parent.categoryid WHERE parent.categoryid>=# GROUP BY parent.categoryid LIMIT 100",
						$nextcategoryid
					));
268

Gideon Greenspan committed
269 270
					if (!count($categories))
						break;
271

Gideon Greenspan committed
272 273 274 275 276 277
					foreach ($categories as $category) {
						$this->sitemap_output('categories/'.implode('/', array_reverse(explode('/', $category['backpath']))), 0.5);
						$nextcategoryid=max($nextcategoryid, $category['categoryid']+1);
					}
				}
			}
278

Gideon Greenspan committed
279 280

		//	Finish up...
281

Gideon Greenspan committed
282
			echo "</urlset>\n";
283

Gideon Greenspan committed
284 285
			return null;
		}
286

Gideon Greenspan committed
287

288
		private function sitemap_output($request, $priority)
Gideon Greenspan committed
289 290
		{
			echo "\t<url>\n".
Gideon Greenspan committed
291
				"\t\t<loc>".qa_xml(qa_path($request, null, qa_opt('site_url')))."</loc>\n".
Gideon Greenspan committed
292 293 294
				"\t\t<priority>".max(0, min(1.0, $priority))."</priority>\n".
				"\t</url>\n";
		}
295

Gideon Greenspan committed
296
	}
297

Gideon Greenspan committed
298 299 300 301

/*
	Omit PHP closing tag to help avoid accidental output
*/