PageRenderTime 56ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/pages/watstemtmijnraad/opensoc/php/indexPage.class.php

https://github.com/openstate/Watstemtmijnraad
PHP | 332 lines | 232 code | 41 blank | 59 comment | 20 complexity | adb0a572567a6564213010445d8cddfb MD5 | raw file
  1. <?php
  2. require_once('Raadsstuk.class.php');
  3. require_once('LocalParty.class.php');
  4. require_once('Region.class.php');
  5. require_once('smarty/dist/plugins/modifier.truncate.php');
  6. /**
  7. * PostgreSQL interval, defines time to live for cache.
  8. * By default 1 day.
  9. */
  10. define('OPENSOCIAL_CACHE_TTL', '1 day');
  11. /**
  12. * Get and echo cached data.
  13. * If data is found, then function should echo the data and return false. If cache
  14. * entry is not found, then function should return true and await opensocial_cache()
  15. * call with data.
  16. *
  17. * @param string $key cache key
  18. * @return bool true if no key was found, thus generate output again
  19. */
  20. function opensocial_readcache($key) {
  21. $res = DBs::inst(DBs::SYSTEM)->query('SELECT data FROM opensocial_cache WHERE cache_key = %s AND created + interval %s > NOW()', $key, OPENSOCIAL_CACHE_TTL)->fetchCell();
  22. if($res) {
  23. echo $res;
  24. return false;
  25. }
  26. return true;
  27. }
  28. /**
  29. * Cache generated data.
  30. * This function will be called if opensocial_readcache() returns true. The data
  31. * will be generated again and passed to this function for storage.
  32. *
  33. * @param string $key the key
  34. * @param string $data json data
  35. */
  36. function opensocial_cache($key, $data) {
  37. //postgres has no insert on duplicate update syntax. if insert fails, we will get exception here, update.
  38. try {
  39. $notupdate = DBs::inst(DBs::SYSTEM)->query('INSERT INTO opensocial_cache(cache_key, data, created) VALUES(%s, %s, NOW())', $key, $data)->affectedRows() > 0;
  40. } catch (Exception $e){
  41. $notupdate = false;
  42. }
  43. if(!$notupdate) { //either failed or INSERT query has returned 0 or NULL (failed silently)
  44. DBs::inst(DBs::SYSTEM)->query('UPDATE opensocial_cache SET data = %s, created = NOW() WHERE cache_key = %s', $data, $key);
  45. }
  46. }
  47. /** Shows raadsstukken of specific politician. */
  48. class IndexPage {
  49. /**
  50. * Returns information about "namespace" and the list of raadsstukken.
  51. * The "namespace" is politician or party or region.
  52. *
  53. * Queries (! - exclusive paramters):
  54. * -- raadsstukken: flag, reqeust raadsstukken
  55. * -- !openid - openid is provided, map openid -> politicus id, politicus mode
  56. * -- !polid - politicus id is provided directly, politicus mode
  57. * -- !partyid - party id is provided directly, party mode
  58. * -- !regionid - region id is provided directly, region mode
  59. * -- limit - limit number of raadstukken
  60. *
  61. * -- regionlist: flag, list active region's
  62. *
  63. * -- partylist: flag, list active parties in given region
  64. * -- regionid - list parties of given region
  65. *
  66. * -- pollist: flag, list active politici
  67. * -- partyid - list politici of given party
  68. *
  69. *
  70. * @param array $get GET parameters
  71. */
  72. public function processGet($get) {
  73. static $params = array('raadsstukken' => 1, 'openid' => 1, 'polid' => 1, 'partyid' => 1, 'regionid' => 1, 'limit' => 1, 'regionlist' => 1,
  74. 'partylist' => 1, 'regionid' => 1, 'pollist' => 1, 'partyid' => 1);
  75. header('Content-type: text/x-json');
  76. //header('Content-type: text/plain');
  77. $host = 'http://'.$_SERVER['HTTP_HOST'];
  78. try {
  79. $key = sha1(serialize(array_intersect_key($get, $params)));
  80. if(opensocial_readcache($key)) {
  81. //dispatch request
  82. if(isset($get['raadsstukken'])) { //raadsstukken list request
  83. $limit = isset($get['limit'])? intval($get['limit']): OPENSOCIAL_RAADSSTUK_LIMIT;
  84. $limit = $limit < 0? OPENSOCIAL_RAADSSTUK_LIMIT: $limit > OPENSOCIAL_MAX_RAADSSTUK_LIMIT? OPENSOCIAL_MAX_RAADSSTUK_LIMIT: $limit;
  85. if(isset($get['openid']) || isset($get['polid'])) { //fetch by politician
  86. if(isset($get['openid'])) { //openid -> politician id mapping
  87. $polid = DBs::inst(DBs::SYSTEM)->query('SELECT po.politician FROM pol_politicians_opensocial po WHERE po.opensocial_id = %s', $get['openid'])->fetchCell();
  88. if(!$polid) {
  89. echo json_encode(array('error' => 'Unknown politician', 'code' => 'id_not_mapped'));
  90. return;
  91. }
  92. } else $polid = intval($get['polid']);
  93. //fetch politician profile info
  94. $pol = new Politician();
  95. try {
  96. $pol->load($polid);
  97. } catch (Exception $e) {
  98. echo json_encode(array('error' => 'Unknown politician', 'code' => 'politician_does_not_exist'));
  99. return;
  100. }
  101. $profile = array(
  102. 'id' => $pol->id,
  103. 'profile_url' => "{$host}/politicians/politician/{$pol->id}",
  104. 'name' => $pol->formatName(),
  105. 'photo' => $pol->photo? "{$host}{$pol->photo}": "{$host}/images/iframe/profile_empty.png",
  106. );
  107. $r = new Raadsstuk();
  108. $raadstukken = $r->listRecentByPolitician($limit, $pol->id);
  109. $data = array(
  110. 'politician' => $profile,
  111. 'raadsstukken' => $this->packRaadsstukken($raadstukken),
  112. );
  113. } elseif(isset($get['partyid'])) { //fetch by party
  114. $party = new LocalParty();
  115. try {
  116. $party->load(intval($get['partyid']));
  117. } catch (Exception $e) {
  118. echo json_encode(array('error' => 'Unknown party', 'code' => 'party_does_not_exist'));
  119. return;
  120. }
  121. $profile = array(
  122. 'id' => $party->party,
  123. 'local_id' => $party->id,
  124. 'name' => $party->party_name,
  125. 'short_name' => $party->party_short,
  126. 'region_id' => $party->region,
  127. 'region_name' => $party->formatRegionName(),
  128. 'profile_url' => "{$host}/parties/party/{$party->party}/?region={$party->region}",
  129. );
  130. //lookup for the raadsstukken
  131. $r = new Raadsstuk();
  132. $raadstukken = $r->listRecentByParty($limit, $party->party, $party->region);
  133. $data = array(
  134. 'party' => $profile,
  135. 'raadsstukken' => $this->packRaadsstukken($raadstukken),
  136. );
  137. } elseif(isset($get['regionid'])) { //fetch by region
  138. $region = new Region();
  139. try {
  140. $region->load(intval($get['regionid']));
  141. } catch (Exception $e) {
  142. echo json_encode(array('error' => 'Unknown region', 'code' => 'region_does_not_exist'));
  143. return;
  144. }
  145. $profile = array(
  146. 'id' => $region->id,
  147. 'name' => $region->formatName(),
  148. 'profile_url' => "{$host}/regions/region/{$region->id}",
  149. );
  150. //lookup for the raadsstukken
  151. $r = new Raadsstuk();
  152. $raadstukken = $r->listRecentByRegion($limit, $region->id);
  153. $data = array(
  154. 'region' => $profile,
  155. 'raadsstukken' => $this->packRaadsstukken($raadstukken),
  156. );
  157. } else {
  158. echo json_encode(array('error' => 'Invalid request', 'code' => 'invalid_request'));
  159. return;
  160. }
  161. } elseif(isset($get['regionlist'])) { //list of regions
  162. $regions = new Region();
  163. //AND t.id IN (SELECT region FROM pol_party_regions pr WHERE NOW() BETWEEN pr.time_start AND pr.time_end)
  164. $reglist = $regions->getList('', 'WHERE t.level > 3 AND t.id IN(SELECT region FROM rs_raadsstukken)', 'ORDER BY t.level ASC, t.name ASC');
  165. $tree = array();
  166. $root = array();
  167. $ids = array();
  168. foreach ($reglist as $reg) {
  169. $tree[$reg->parent][$reg->id] = $reg;
  170. if($reg->level <= 4) $root[$reg->id] = $reg;
  171. $ids[] = $reg->parent;
  172. }
  173. //fetch empty parents that have non empty children
  174. $reglist = $regions->getList('', 'WHERE t.level > 3 AND t.id IN ('.implode(', ', $ids).')', 'ORDER BY t.level ASC, t.name ASC');
  175. foreach ($reglist as $reg) {
  176. $tree[$reg->parent][$reg->id] = $reg;
  177. if($reg->level <= 3 && !isset($root[$reg->id])) $root[$reg->id] = $reg;
  178. }
  179. $data = $this->convRegTree($root, $tree, $host);
  180. } elseif(isset($get['partylist'])) { //parties list
  181. if(!isset($get['regionid'])) {
  182. echo json_encode(array('error' => 'Invalid request', 'code' => 'invalid_request'));
  183. return;
  184. }
  185. $party = new LocalParty();
  186. $parties = $party->getList('', 'WHERE NOW() BETWEEN time_start AND time_end AND region = '.intval($get['regionid']), 'ORDER BY p.name');
  187. $data = array();
  188. foreach ($parties as $party) {
  189. $p = array(
  190. 'id' => $party->party,
  191. 'local_id' => $party->id,
  192. 'name' => $party->party_name,
  193. 'short_name' => $party->party_short,
  194. 'region_id' => $party->region,
  195. 'region_name' => $party->formatRegionName(),
  196. 'profile_url' => "{$host}/parties/party/{$party->party}/?region={$party->region}",
  197. );
  198. array_push($data, $p);
  199. }
  200. } elseif(isset($get['pollist'])) { //list of politicians
  201. if(!isset($get['partyid'])) {
  202. echo json_encode(array('error' => 'Invalid request', 'code' => 'invalid_request'));
  203. return;
  204. }
  205. $pol = new Politician();
  206. //Database is trash, don't check anything, they like it: AND pf.time_start >= pr.time_start AND pf.time_end <= pr.time_end
  207. $politicians = $pol->getList('JOIN pol_politician_functions pf ON t.id = pf.politician JOIN pol_party_regions pr ON pf.party = pr.party AND pf.region = pr.region',
  208. 'WHERE pr.id = '.intval($get['partyid']).' AND NOW() BETWEEN pf.time_start AND pf.time_end AND t.def_party IS NULL');
  209. $data = array();
  210. foreach ($politicians as $pol) {
  211. $p = array(
  212. 'id' => $pol->id,
  213. 'profile_url' => "{$host}/politicians/politician/{$pol->id}",
  214. 'name' => $pol->formatName(),
  215. 'photo' => $pol->photo? "{$host}{$pol->photo}": "{$host}/images/iframe/profile_empty.png",
  216. );
  217. array_push($data, $p);
  218. }
  219. } else {
  220. //unknown/invalid request
  221. echo json_encode(array('error' => 'Invalid request', 'code' => 'invalid_request'));
  222. return;
  223. }
  224. // request dispatched, cache data
  225. $data = json_encode($data);
  226. opensocial_cache($key, $data);
  227. echo $data;
  228. }
  229. } catch (Exception $e) {
  230. echo json_encode(array('error' => 'Internal error', 'code' => 'internal'));
  231. }
  232. }
  233. public function show($smarty) {
  234. }
  235. private function convRegTree($list, $tree, $host) {
  236. $ret = array();
  237. foreach ($list as $reg) {
  238. $r = array(
  239. 'id' => $reg->id,
  240. 'name' => $reg->formatName(),
  241. 'profile_url' => "{$host}/regions/region/{$reg->id}",
  242. );
  243. if(isset($tree[$reg->id]) && !empty($tree[$reg->id])) {
  244. $r['children'] = $this->convRegTree($tree[$reg->id], $tree, $host);
  245. }
  246. array_push($ret, $r);
  247. }
  248. return $ret;
  249. }
  250. /** Format raadsstukken into simple dict */
  251. private function packRaadsstukken($list) {
  252. static $result_map = array(
  253. 0 => 'new',
  254. 1 => 'pro',
  255. 2 => 'contra',
  256. );
  257. static $votemap = array(
  258. 0 => 'pro',
  259. 1 => 'contra',
  260. 2 => 'abstain',
  261. 3 => 'absent',
  262. );
  263. $ret = array();
  264. $keys = array('id', 'title', 'vote_date', 'region_name', 'level_name', 'type_name', 'submit_type_name'); //, 'result', 'vote_0', 'vote_1', 'vote_2', 'vote_3', 'polvote');
  265. $host = 'http://'.$_SERVER['HTTP_HOST'];
  266. foreach ($list as $rad) {
  267. $rec = array();
  268. foreach ($keys as $k) $rec[$k] = $rad->$k;
  269. //mapped info
  270. $rec['result'] = $result_map[$rad->result];
  271. $rec['count_pro'] = $rad->vote_0;
  272. $rec['count_contra'] = $rad->vote_1;
  273. $rec['count_abstain'] = $rad->vote_2;
  274. $rec['count_absent'] = $rad->vote_3;
  275. //extra info
  276. if($rad->hasProperty('polvote')) $rec['polvote'] = $votemap[$rad->polvote];
  277. if($rad->hasProperty('party_vote_0')) {
  278. $rec['party_vote_pro'] = $rad->party_vote_0;
  279. $rec['party_vote_contra'] = $rad->party_vote_1;
  280. $rec['party_vote_abstain'] = $rad->party_vote_2;
  281. $rec['party_vote_absent'] = $rad->party_vote_3;
  282. }
  283. $txt = str_replace('><', '> <', $rad->summary);
  284. $rec['summary'] = smarty_modifier_truncate(strip_tags($txt), OPENSOCIAL_RAADSSTIK_SUMMARY_LIMIT);
  285. $rec['view_url'] = "{$host}/raadsstukken/raadsstuk/{$rad->id}";
  286. array_push($ret, $rec);
  287. }
  288. return $ret;
  289. }
  290. }
  291. ?>