function delete($id = FALSE) { if ($id) { $law = new Law($id); $law->delete(); set_notify('success', lang('delete_data_complete')); } redirect($_SERVER['HTTP_REFERER']); }
</section>'; } /* * If we have a list of related laws, list them. * Note that Solr < 4.6 will probably die horribly trying this. * We catch any exceptions as a result and go about our business. */ try { $search_client = new SearchIndex(array('config' => json_decode(SEARCH_CONFIG, TRUE))); $related_laws = $search_client->find_related($law, 3); if ($related_laws && count($related_laws->get_results()) > 0) { $sidebar .= ' <section class="related-group grid-box" id="related-links"> <h1>Related Laws</h1> <ul id="related">'; $related_law = new Law(); foreach ($related_laws->get_results() as $result) { $related_law->law_id = $result->law_id; $related_law->get_law(); $related_law->permalink = $related_law->get_url($result->law_id); $sidebar .= '<li>' . SECTION_SYMBOL . ' <a href="' . $related_law->permalink->url . '">' . $related_law->section_number . '</a> ' . $related_law->catch_line . '</li>'; } $sidebar .= ' </ul> </section>'; } } catch (Exception $exception) { // Do nothing. } /* * If we have citation data and it's formatted properly, display it.
function handle($args) { /* * Create a new instance of the class that handles information about individual laws. */ $laws = new Law(); /* * Instruct the Law class on what, specifically, it should retrieve. */ $laws->config->get_text = TRUE; $laws->config->get_structure = TRUE; $laws->config->get_amendment_attempts = FALSE; $laws->config->get_court_decisions = TRUE; $laws->config->get_metadata = TRUE; $laws->config->get_references = TRUE; $laws->config->get_related_laws = TRUE; /* * Pass the requested section number to Law. */ $laws->section_number = $args['identifier']; $laws->law_id = $args['relational_id']; /* * Get a list of all of the basic information that we have about this section. */ $response = $laws->get_law(); /* * If, for whatever reason, this section is not found, return an error. */ if ($response === false) { $this->handleNotFound(); } else { /* * Eliminate the listing of all other sections in the chapter that contains this section. That's * returned by our internal API by default, but it's not liable to be useful to folks receiving * this data. */ unset($response->chapter_contents); } /* * If the request contains a specific list of fields to be returned. */ if (isset($_GET['fields'])) { /* * Turn that list into an array. */ $returned_fields = explode(',', urldecode($_GET['fields'])); foreach ($returned_fields as &$field) { $field = trim($field); } /* * It's essential to unset $field at the conclusion of the prior loop. */ unset($field); /* * Step through our response fields and eliminate those that aren't in the requested list. */ foreach ($response as $field => &$value) { if (in_array($field, $returned_fields) === false) { unset($response->{$field}); } } } $this->render($response, 'OK'); }
/** * Returns count of tag's laws * @return int */ public function getLawCount() { return Law::find()->where(['tagYes' => $this->name])->orWhere(['tagNo' => $this->name])->count(); }
<?php /** * The page that displays an individual law. * * PHP version 5 * * @license http://www.gnu.org/licenses/gpl.html GPL 3 * @version 0.8 * @link http://www.statedecoded.com/ * @since 0.1 */ /* * Create a new instance of Law. */ $laws = new Law(); /* * Use the ID passed to look up the law. */ if (isset($args['relational_id'])) { $laws->law_id = filter_var($args['relational_id'], FILTER_SANITIZE_STRING); /* * Retrieve a copy of the law. */ $law = $laws->get_law(); } if (!isset($law) || $law === FALSE) { send_404(); } /* * Store a record that this section was viewed.
/** * Create and save a sitemap.xml * * List every law in this legal code and create an XML file with an entry for every one of them. */ function generate_sitemap() { $this->logger->message('Generating sitemap.xml', 3); /* * The sitemap.xml file must be kept in the site root, as per the standard. */ $sitemap_file = WEB_ROOT . '/sitemap.xml'; if (!is_writable($sitemap_file)) { $this->logger->message('Do not have permissions to write to sitemap.xml', 3); return FALSE; } /* * List the ID of every law in the current edition. We cut it off at 50,000 laws because * that is the sitemap.xml limit. */ $sql = 'SELECT id FROM laws WHERE edition_id = :edition_id LIMIT 50000'; $sql_args = array(':edition_id' => EDITION_ID); $statement = $this->db->prepare($sql); $result = $statement->execute($sql_args); if ($result === FALSE || $statement->rowCount() == 0) { $this->logger->message('No laws could be found to export to the sitemap', 3); return FALSE; } /* * Create a new XML file, using the sitemap.xml schema. */ $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" />'); /* * Create a new instance of the class that handles information about individual laws. */ $laws = new Law(); /* * Iterate through every section ID. */ while ($section = $statement->fetch(PDO::FETCH_OBJ)) { /* * Instruct the Law class on what, specifically, it should retrieve. (Very little.) */ $laws->config->get_all = FALSE; $laws->config->get_text = FALSE; $laws->config->get_structure = FALSE; $laws->config->get_amendment_attempts = FALSE; $laws->config->get_court_decisions = FALSE; $laws->config->get_metadata = FALSE; $laws->config->get_references = FALSE; $laws->config->get_related_laws = FALSE; $laws->config->render_html = FALSE; /* * Get the law in question. */ $laws->law_id = $section->id; $law = $laws->get_law(); /* * Add a record of this law to the XML. */ $url = $xml->addChild('url'); $url->addchild('loc', $law->url); $url->addchild('changefreq', 'monthly'); } /* * Save the resulting file. */ file_put_contents($sitemap_file, $xml->asXML()); return TRUE; }
/** * Retrieve all of the material relevant to a given law. */ public function get_law() { /* * If neither a section number nor a law ID has been passed to this function, then there's * nothing to do. */ if (!isset($this->section_number) && !isset($this->law_id)) { return FALSE; } /* * If we haven't specified which fields that we want, then assume that we want all of them. */ if (!isset($this->config) || !is_object($this->config)) { $this->config = new StdClass(); $this->config->get_all = TRUE; } /* * Define the level of detail that we want from this method. By default, we return * everything that we have for this law. */ if (!isset($this->config) || isset($this->config->get_all) && $this->config->get_all == TRUE) { $this->config->get_text = TRUE; $this->config->get_structure = TRUE; $this->config->get_amendment_attempts = TRUE; $this->config->get_court_decisions = TRUE; $this->config->get_metadata = TRUE; $this->config->get_references = TRUE; $this->config->get_tags = TRUE; $this->config->render_html = TRUE; } /* * Assemble the query that we'll use to get this law. */ $sql = 'SELECT id AS section_id, structure_id, edition_id, section AS section_number, catch_line, history, text AS full_text, order_by FROM laws'; $sql_args = array(); /* * If we're requesting a specific law by ID. */ if (isset($this->law_id)) { /* * If it's just a single law ID, then just request the one. */ if (!is_array($this->law_id)) { $sql .= ' WHERE id = :id'; $sql_args[':id'] = $this->law_id; } elseif (is_array($this->law_id)) { $sql .= ' WHERE ('; /* * Step through the list. */ $law_count = count($this->law_id); for ($i = 0; $i < $law_count; $i++) { $sql .= " id = :id{$i}"; $sql_args[":id{$i}"] = $this->law_id[$i]; if ($i < $law_count - 1) { $sql .= ' OR'; } } $sql .= ')'; } } else { $sql .= ' WHERE section = :section_number AND edition_id = :edition_id'; $sql_args[':section_number'] = $this->section_number; if (isset($this->edition_id)) { $sql_args[':edition_id'] = $this->edition_id; } else { $sql_args[':edition_id'] = EDITION_ID; } } $statement = $this->db->prepare($sql); $result = $statement->execute($sql_args); if ($result === FALSE || $statement->rowCount() == 0) { return FALSE; } /* * Return the result as an object. */ $tmp = $statement->fetch(PDO::FETCH_OBJ); /* * Bring this law into the object scope. */ foreach ($tmp as $key => $value) { $this->{$key} = $value; } /* * Clean up the typography in the full text. */ $this->full_text = wptexturize($this->full_text); /* * Now get the text for this law, subsection by subsection. */ if ($this->config->get_text === TRUE) { /* * When invoking this method in a loop, $this->text can pile up on itself. If the text * property is already set, clear it out. */ if (isset($this->text)) { unset($this->text); } $sql = 'SELECT id, text, type, (SELECT GROUP_CONCAT(identifier ORDER BY sequence ASC SEPARATOR "|") FROM text_sections WHERE text_id=text.id GROUP BY text_id) AS prefixes FROM text WHERE law_id = :law_id ORDER BY text.sequence ASC'; $sql_args = array(':law_id' => $this->section_id); $statement = $this->db->prepare($sql); $result = $statement->execute($sql_args); /* * If the query fails, or if no results are found, return false -- we can't make a * match. */ if ($result === FALSE || $statement->rowCount() == 0) { return FALSE; } /* * Iterate through all of the sections of text to save to our object. */ $i = 0; while ($tmp = $statement->fetch(PDO::FETCH_OBJ)) { $tmp->prefixes = explode('|', $tmp->prefixes); $tmp->prefix = end($tmp->prefixes); $tmp->entire_prefix = implode('', $tmp->prefixes); $tmp->prefix_anchor = str_replace(' ', '_', $tmp->entire_prefix); $tmp->level = count($tmp->prefixes); /* * Pretty it up, converting all straight quotes into directional quotes, double * dashes into em dashes, etc. */ if ($tmp->type != 'table') { $tmp->text = wptexturize($tmp->text); } /* * Append this section. */ if (!isset($this->text)) { $this->text = new StdClass(); } $this->text->{$i} = $tmp; $i++; } } /* * Determine this law's structural position. */ if ($this->config->get_structure = TRUE) { /* * Create a new instance of the Structure class. */ $struct = new Structure(); /* * Provide the edition ID so that we know which edition to query. */ if (isset($this->edition_id)) { $struct->edition_id = $this->edition_id; } else { $struct->edition_id = EDITION_ID; } /* * Our structure ID provides a starting point to identify this law's ancestry. */ $struct->id = $this->structure_id; /* * Save the law's ancestry. */ $this->ancestry = $struct->id_ancestry(); /* * Short of a parser error, there’s no reason why a law should not have an ancestry. In * case of this unlikely possibility, just erase the false element. */ if ($this->ancestry === FALSE) { unset($this->ancestry); } /* * Get the listing of all other sections in the structural unit that contains this * section. */ $this->structure_contents = $struct->list_laws(); /* * Figure out what the next and prior sections are (we may have 0-1 of either). Iterate * through all of the contents of the chapter. (It's possible that there are no next or * prior sections, such as in a single-item structural unit.) */ if ($this->structure_contents !== FALSE) { $tmp = count((array) $this->structure_contents); for ($i = 0; $i < $tmp; $i++) { /* * When we get to our current section, that's when we get to work. */ if ($this->structure_contents->{$i}->id == $this->section_id) { $j = $i - 1; $k = $i + 1; if (isset($this->structure_contents->{$j})) { $this->previous_section = $this->structure_contents->{$j}; } if (isset($this->structure_contents->{$k})) { $this->next_section = $this->structure_contents->{$k}; } break; } } } } /* * Gather all metadata stored about this law. */ if ($this->config->get_metadata == TRUE) { $this->metadata = Law::get_metadata(); } /* * Gather any tags applied to this law. */ if (isset($this->config->get_tags) && $this->config->get_tags == TRUE) { $sql = 'SELECT text FROM tags WHERE law_id = ' . $this->db->quote($this->section_id); $result = $this->db->query($sql); if ($result !== TRUE && $result->rowCount() > 0) { $this->tags = new stdClass(); $i = 0; while ($tag = $result->fetch(PDO::FETCH_OBJ)) { $this->tags->{$i} = $tag->text; $i++; } } } /* * Create a new instance of the State() class. */ $state = new State(); $state->section_id = $this->section_id; $state->section_number = $this->section_number; /* * Get the amendment attempts for this law and include those (if there are any). But * only if we have specifically requested this data. That's because, on most installations, * this will be making a call to a third-party service (e.g., Open States), and such a call * is expensive. */ if ($this->config->get_amendment_attempts == TRUE) { if (method_exists($state, 'get_amendment_attempts')) { if ($state->get_amendment_attempts() !== FALSE) { $this->amendment_attempts = $state->bills; } } } /* * Get the court decisions that affect this law and include those (if there are any). But * only if we have specifically requested this data. That's because, on most installations, * this will be making a call to a third-party service and such a call is expensive. */ if ($this->config->get_court_decisions == TRUE) { /* * If we already have this data cached as metadata, and it's not blank. (We cache not * just when there are court decisions for a given law, but also when there are no * court decisions for a law. "No court decisions" is represented as an empty record.) */ if (isset($this->metadata->court_decisions) && !empty($this->metadata->court_decisions)) { $this->court_decisions = $this->metadata->court_decisions; } else { if (method_exists($state, 'get_court_decisions')) { if ($state->get_court_decisions() !== FALSE) { $this->court_decisions = $state->decisions; } } } /* * If we've cached the fact that there are no court decisions. */ if (isset($this->court_decisions->{0}) && $this->court_decisions->{0} == FALSE) { unset($this->court_decisions); } } /* * Get the URL for this law on its official state web page. */ if (method_exists($state, 'official_url')) { $this->official_url = $state->official_url(); } /* * Translate the history of this law into plain English. */ if (method_exists($state, 'translate_history')) { if (isset($this->metadata->history)) { $state->history = $this->metadata->history; $this->history_text = $state->translate_history(); } } /* * Generate citations for this law. */ if (method_exists($state, 'citations')) { $state->section_number = $this->section_number; $state->citations(); $this->citation = $state->citation; } /* * Get the references to this law among other laws and include those (if there are any). */ if ($this->config->get_references == TRUE) { $this->references = Law::get_references(); $this->refers_to = Law::get_references(true); } /* * Pretty up the text for the catch line. */ $this->catch_line = wptexturize($this->catch_line); /* * Provide the URL for this section. */ $sql = 'SELECT url, token FROM permalinks WHERE relational_id = :id AND object_type = :object_type'; $statement = $this->db->prepare($sql); $sql_args = array(':id' => $this->section_id, ':object_type' => 'law'); $result = $statement->execute($sql_args); if ($result !== FALSE && $statement->rowCount() > 0) { $permalink = $statement->fetch(PDO::FETCH_OBJ); $this->url = $permalink->url; $this->token = $permalink->token; } /* * List the URLs for the textual formats in which this section is available. */ if (!isset($this->formats)) { $this->formats = new StdClass(); } $this->formats->txt = substr($this->url, 0, -1) . '.txt'; $this->formats->json = substr($this->url, 0, -1) . '.json'; $this->formats->xml = substr($this->url, 0, -1) . '.xml'; /* * Create metadata in the Dublin Core format. */ $this->dublin_core = new stdClass(); $this->dublin_core->Title = $this->catch_line; $this->dublin_core->Type = 'Text'; $this->dublin_core->Format = 'text/html'; $this->dublin_core->Identifier = SECTION_SYMBOL . ' ' . $this->section_number; $this->dublin_core->Relation = LAWS_NAME; /* * If the request specifies that rendered HTML should be returned, then generate that. */ if (isset($this->config->render_html) && $this->config->render_html === TRUE) { $this->html = Law::render(); } /* * Provide a plain text version of this law. */ $this->plain_text = Law::render_plain_text(); /* * Provide a plain text document header. */ $this->plain_text = str_repeat(' ', round((81 - strlen(LAWS_NAME)) / 2)) . strtoupper(LAWS_NAME) . "\n\n" . wordwrap(strtoupper($this->catch_line) . ' (' . SECTION_SYMBOL . ' ' . $this->section_number . ')', 80, "\n", TRUE) . "\n\n" . $this->plain_text; if (!empty($this->history)) { $this->plain_text .= "\n" . wordwrap('HISTORY: ' . $this->history, 80, "\n", TRUE); } $law = $this; unset($law->config); return $law; }
} else { $body .= '<p>No results found.</p>'; } } else { /* * Start the DIV that stores all of the search results. */ $body .= ' <div class="search-results"> <p>' . number_format($results->get_count()) . ' results found.</p> <ul>'; /* * Iterate through the results. */ global $db; $law = new Law(array('db' => $db)); foreach ($results->get_results() as $result) { $law->law_id = $result->law_id; $law->get_law(); $url = $law->get_url($result->law_id); $url_string = $url->url; if (strpos($url, '?') !== FALSE) { $url_string .= '?'; } else { $url_string .= '*'; } $url_string .= 'q=' . urlencode($q); $body .= '<li><div class="result">'; $body .= '<h1><a href="' . $url_string . '">'; if (strlen($result->catch_line)) { $body .= $result->catch_line;
function handle($args) { /* * If we have received neither a term nor a section, we can't do anything. */ if (empty($args['term']) && empty($_GET['section'])) { json_error('Neither a dictionary term nor a section number have been provided.'); die; } /* * Clean up the term. */ $term = filter_var($args['term'], FILTER_SANITIZE_STRING); /* * If a section has been specified, then clean that up. */ if (isset($_GET['section'])) { $section = filter_input(INPUT_GET, 'section', FILTER_SANITIZE_STRING); } $dict = new Dictionary(); /* * Get the definitions for the requested term, if a term has been requested. */ if (!empty($args['term'])) { if (isset($section)) { $dict->section_number = $section; } $dict->term = $term; $dictionary = $dict->define_term(); /* * If, for whatever reason, this term is not found, return an error. */ if ($dictionary === FALSE) { $response = array('definition' => 'Definition not available.'); } else { /* * Uppercase the first letter of the first (quoted) word. We perform this twice because * some egal codes begin the definition with a quotation mark and some do not. (That is, * some write '"Whale" is a large sea-going mammal' and some write 'Whale is a large * sea-going mammal.") */ if (preg_match('/[A-Za-z]/', $dictionary->definition[0]) === 1) { $dictionary->definition[0] = strtoupper($dictionary->definition[0]); } elseif (preg_match('/[A-Za-z]/', $dictionary->definition[1]) === 1) { $dictionary->definition[1] = strtoupper($dictionary->definition[1]); } /* * If the request contains a specific list of fields to be returned. */ if (isset($_GET['fields'])) { /* * Turn that list into an array. */ $returned_fields = explode(',', urldecode($_GET['fields'])); foreach ($returned_fields as &$field) { $field = trim($field); } /* * It's essential to unset $field at the conclusion of the prior loop. */ unset($field); foreach ($dictionary as &$term) { /* * Step through our response fields and eliminate those that aren't in the * requested list. */ foreach ($term as $field => &$value) { if (in_array($field, $returned_fields) === FALSE) { unset($term->{$field}); } } } } /* * If a section has been specified, then simplify this response by returning just a * single definition. */ if (isset($section)) { $dictionary = $dictionary->{0}; } /* * Rename this variable to use the expected name. */ $response = $dictionary; } // end else if term is found } elseif (!empty($_GET['section'])) { /* * Get the structural ID of the container for this section. */ $law = new Law(); $law->section_number = $section; $law->config = FALSE; $result = $law->get_law(); if ($result == FALSE) { $response = array('terms' => 'Term list not available.'); } else { /* * Now get the term list. */ $dict->section_id = $law->section_id; $dict->structure_id = $law->structure_id; $response = $dict->term_list(); if ($response == FALSE) { $response = array('terms' => 'Term list not available.'); } } } // end elseif (!empty($args['section'])) $this->render($response, 'OK', $_REQUEST['callback']); }
/** * @return Law */ public function getLaw() { return Law::find($this->law_id); }
function handle($args) { /* * Make sure we have a search term. */ if (!isset($args['term']) || empty($args['term'])) { json_error('Search term not provided.'); die; } /* * Clean up the search term. */ $term = filter_var($args['term'], FILTER_SANITIZE_STRING); /* * Determine if the search results should display detailed information about each law. */ if (!isset($_GET['detailed']) || empty($_GET['detailed'])) { $detailed = FALSE; } else { $detailed = filter_var($_GET['detailed'], FILTER_SANITIZE_STRING); if ($detailed == "true") { $detailed = TRUE; } elseif ($detailed != "false") { $detailed = FALSE; } else { $detailed = FALSE; } } /* * Intialize Solarium. */ $client = new Solarium_Client($GLOBALS['solr_config']); /* * Set up our query. */ $query = $client->createSelect(); $query->setQuery($term); /* * We want the most useful bits extracted as search results snippets. */ $hl = $query->getHighlighting(); $hl->setFields('catch_line, text'); /* * Specify that we want the first 100 results. */ $query->setStart(0)->setRows(100); /* * Execute the query. */ $search_results = $client->select($query); /* * Display uses of the search terms in a preview of the result. */ $highlighted = $search_results->getHighlighting(); /* * If there are no results. */ if (count($search_results) == 0) { $response->records = 0; $response->total_records = 0; } /* * If we have results. */ /* * Instantiate the Law class. */ $law = new Law(); /* * Save an array of the legal code's structure, which we'll use to properly identify the structural * data returned by Solr. We hack off the last element of the array, since that identifies the laws * themselves, not a structural unit. */ $code_structures = array_slice(explode(',', STRUCTURE), 0, -1); $i = 0; foreach ($search_results as $document) { /* * Attempt to display a snippet of the indexed law. */ $snippet = $highlighted->getResult($document->id); if ($snippet != FALSE) { /* * Build the snippet up from the snippet object. */ foreach ($snippet as $field => $highlight) { $response->results->{$i}->excerpt .= strip_tags(implode(' ... ', $highlight)) . ' ... '; } /* * Use an appropriate closing ellipsis. */ if (substr($response->results->{$i}->excerpt, -6) == '. ... ') { $response->results->{$i}->excerpt = substr($response->results->{$i}->excerpt, 0, -6) . '....'; } $response->results->{$i}->excerpt = trim($response->results->{$i}->excerpt); } /* * At the default level of verbosity, just give the data indexed by Solr, plus the URL. */ if ($detailed === FALSE) { /* * Store the relevant fields within the response we'll send. */ $response->results->{$i}->section_number = $document->section; $response->results->{$i}->catch_line = $document->catch_line; $response->results->{$i}->text = $document->text; $response->results->{$i}->url = $law->get_url($document->section); $response->results->{$i}->score = $document->score; $response->results->{$i}->ancestry = (object) array_combine($code_structures, explode('/', $document->structure)); } else { $law->section_number = $document->section; $response->results->{$i} = $law->get_law(); $response->results->{$i}->score = $document->score; } $i++; } /* * Provide the total number of available documents, beyond the number returned by or available * via the API. */ $response->total_records = $search_results->getNumFound(); /* * If the request contains a specific list of fields to be returned. */ if (isset($args['fields'])) { /* * Turn that list into an array. */ $returned_fields = explode(',', urldecode(filter_var($args['fields'], FILTER_SANITIZE_STRING))); foreach ($returned_fields as &$field) { $field = trim($field); } /* * It's essential to unset $field at the conclusion of the prior loop. */ unset($field); /* * Step through our response fields and eliminate those that aren't in the requested list. */ foreach ($response as $field => &$value) { if (in_array($field, $returned_fields) === false) { unset($response->{$field}); } } } $this->render($response, 'OK'); }
} else { /* * Store the total number of documents returned by this search. */ $total_results = $results->getNumFound(); /* * Start the DIV that stores all of the search results. */ $body .= ' <div class="search-results"> <p>' . number_format($total_results) . ' results found.</p> <ul>'; /* * Iterate through the results. */ $law = new Law(); foreach ($results as $result) { $url = $law->get_url($result->section); $body .= '<li><div class="result">'; $body .= '<h1><a href="' . $url . '">' . $result->catch_line . ' (' . SECTION_SYMBOL . ' ' . $result->section . ')</a></h1>'; /* * Display this law's structural ancestry as a breadcrumb trail. */ $body .= '<div class="breadcrumbs"><ul>'; $ancestry = explode('/', $result->structure); foreach ($ancestry as $structure) { $body .= '<li><a>' . $structure . '</a></li>'; } $body .= '</ul></div>'; /* * Attempt to display a snippet of the indexed law, highlighting the use of the search
/** * This is used as the preg_replace_callback function that inserts section links into text. */ function replace_sections($matches) { /* * PCRE provides an array-based match listing. We only want the first one. */ $match = $matches[0]; /* * If the section symbol prefixes this match, hack it off. */ if (substr($match, 0, strlen(SECTION_SYMBOL)) == SECTION_SYMBOL) { $match = substr($match, strlen(SECTION_SYMBOL . ' ')); } /* * Create an instance of the Law class. */ $law = new Law(); /* * Just find out if this law exists. */ $law->section_number = $match; $section = $law->exists(); /* * If this isn't a valid section number, then just return the match verbatim -- there's no * link to be provided. */ if ($section === FALSE) { return $matches[0]; } return '<a class="law" href="/' . $match . '/">' . $matches[0] . '</a>'; }
/** * Get the definition for a given term for a given section of code. */ function define_term() { /* * We're going to need access to the database connection throughout this class. */ global $db; /* * If no term has been defined, there is nothing to be done. */ if (!isset($this->term)) { return FALSE; } /* * Determine the structural heritage of the provided section number and store it in an * array. */ if (isset($this->section_number) || isset($this->law_id)) { $heritage = new Law(); $heritage->config = new stdClass(); $heritage->config->get_structure = TRUE; if (isset($this->section_number)) { $heritage->section_number = $this->section_number; } elseif (isset($this->law_id)) { $heritage->law_id = $this->law_id; } if (isset($this->edition_id)) { $heritage->edition_id = $this->edition_id; } $law = $heritage->get_law(); $ancestry = array(); foreach ($law->ancestry as $tmp) { $ancestry[] = $tmp->id; } } /* * We want to check if the term is in all caps. If it is, then we want to keep it in * all caps to query the database. Otherwise, we lowercase it. That is, "Board" should be looked * up as "board," but "NAIC" should be looked up as "NAIC." */ for ($i = 0; $i < strlen($this->term); $i++) { /* * If there are any uppercase characters, then make this PCRE string case * sensitive. */ if (ord($this->term[$i]) >= 97 && ord($this->term[$i]) <= 122) { $lowercase = TRUE; break; } } if ($lowercase === TRUE) { $this->term = strtolower($this->term); } /* * If the last character in this word is an "s," then it might be a plural, in which * case we need to search for this and without its plural version. */ if (substr($this->term, -1) == 's') { $plural = TRUE; } /* * This is a tortured assembly of a query. The idea is to provide flexibility on a pair of * axes. The first is to support both plural and singular terms. The second is to support * queries with and without section numbers, to provide either the one true definition for * a term within a given scope or all definitions in the whole code. */ $sql = 'SELECT dictionary.term, dictionary.definition, dictionary.scope, laws.section AS section_number, laws.id AS law_id, permalinks.url AS url FROM dictionary LEFT JOIN laws ON dictionary.law_id=laws.id LEFT JOIN permalinks ON permalinks.relational_id=laws.id AND permalinks.object_type = :object_type AND permalinks.preferred=1 WHERE (dictionary.term = :term'; $sql_args = array(':term' => $this->term, ':object_type' => 'law'); if ($plural === TRUE) { $sql .= ' OR dictionary.term = :term_single'; $sql_args[':term_single'] = substr($this->term, 0, -1); } $sql .= ') '; if (isset($this->section_number) || isset($this->law_id)) { $sql .= 'AND ('; $ancestor_count = count($ancestry); for ($i = 0; $i < $ancestor_count; $i++) { $sql .= "(dictionary.structure_id = :structure_id{$i}) OR "; $sql_args[":structure_id{$i}"] = $ancestry[$i]; } $sql .= ' (dictionary.scope = :scope) OR '; if (isset($this->section_number)) { $sql .= '(laws.section = :section_number)'; $sql_args[':section_number'] = $this->section_number; } else { $sql .= '(laws.id = :law_id)'; $sql_args[':law_id'] = $this->law_id; } $sql .= ') AND dictionary.edition_id = :edition_id '; $sql_args[':scope'] = 'global'; $sql_args[':edition_id'] = $this->edition_id; } $sql .= 'ORDER BY dictionary.scope_specificity '; if (isset($this->section_number) || isset($this->law_id)) { $sql .= 'LIMIT 1'; } $statement = $db->prepare($sql); $result = $statement->execute($sql_args); /* * If the query succeeds, great, retrieve it. */ if ($result !== FALSE && $statement->rowCount() > 0) { /* * Get all results. */ $dictionary = new stdClass(); $i = 0; while ($term = $statement->fetch(PDO::FETCH_OBJ)) { $term->formatted = wptexturize($term->definition) . ' (<a href="' . $term->url . '">' . $term->section_number . '</a>)'; $dictionary->{$i} = $term; $i++; } } else { /* * Assemble the SQL. */ $sql = 'SELECT term, definition, source, source_url AS url FROM dictionary_general WHERE term = :term'; $sql_args = array(':term' => $this->term); if ($plural === TRUE) { $sql .= ' OR term = :term_single'; $sql_args[':term_single'] = substr($this->term, 0, -1); } $sql .= ' LIMIT 1'; $statement = $db->prepare($sql); $result = $statement->execute($sql_args); /* * If the query fails, or if no results are found, return false -- we have no terms for * this structural unit. */ if ($result === FALSE || $statement->rowCount() < 1) { return FALSE; } /* * Get the first result. Assemble a slightly different response than for a custom term. * We assign this to the first element of an object because that is the format that the * API expects to receive a list of terms in. In this case, we have just one term. */ $dictionary->{0} = $statement->fetch(PDO::FETCH_OBJ); $dictionary->{0}->formatted = wptexturize($dictionary->{0}->definition) . ' (<a href="' . $dictionary->{0}->url . '">' . $dictionary->{0}->source . '</a>)'; } return $dictionary; }
public function index_laws($args) { if (!isset($this->edition)) { $edition_obj = new Edition(array('db' => $this->db)); $this->edition = $edition_obj->current(); } if (!isset($this->edition)) { throw new Exception('No edition, cannot index laws.'); } if ($this->edition->current != '1') { $this->logger->message('The edition is not current, skipping the update of the search ' . ' index', 9); return; } if (!defined('SEARCH_CONFIG')) { $this->logger->message('Solr is not in use, skipping index', 9); return; } else { /* * Index the laws. */ $this->logger->message('Updating search index', 5); $this->logger->message('Indexing laws', 6); $search_index = new SearchIndex(array('config' => json_decode(SEARCH_CONFIG, TRUE))); $law_obj = new Law(array('db' => $this->db)); $result = $law_obj->get_all_laws($this->edition->id, true); $search_index->start_update(); while ($law = $result->fetch()) { // Get the full data of the actual law. $document = new Law(array('db' => $this->db)); $document->law_id = $law['id']; $document->config->get_all = TRUE; $document->get_law(); // Bring over our edition info. $document->edition = $this->edition; try { $search_index->add_document($document); } catch (Exception $error) { $this->logger->message('Search index error "' . $error->getStatusMessage() . '"', 10); return FALSE; } } $search_index->commit(); // $this->logger->message('Indexing structures', 6); ### TODO: Index structures $this->logger->message('Laws were indexed', 5); return TRUE; } }
/** * Get a collection of the laws most similar to the present law. */ function get_related() { /* * The number of results to return. The default is 5. */ if (!isset($this->num_results)) { $this->num_results = 5; } /* * Intialize Solarium. */ $client = new Solarium_Client($GLOBALS['solr_config']); if ($client === FALSE) { return FALSE; } /* * Create a MoreLikeThis query instance. */ $query = $client->createMoreLikeThis(); /* * Note that we have to escape colons in this query. */ $query->setQuery('section:' . str_replace(':', '\\:', $this->section_number)); $query->setMltFields('text,tags,catch_line'); $query->setMatchInclude(TRUE); $query->setStart(0)->setRows($this->num_results); /* * Execute the query and return the result. */ $results = $client->select($query); /* * If our query fails. */ if ($results === FALSE) { return FALSE; } /* * Create a new, blank object to store our related sections. */ $related = new StdClass(); /* * Iterate through the returned documents */ $i = 0; foreach ($results as $document) { $law = new Law(); $law->law_id = $document->id; $law->get_law(); $related->{$i} = $law; $i++; } return TRUE; }
/** * This is used as the preg_replace_callback function that inserts section links into text. */ function replace_sections($matches) { /* * PCRE provides an array-based match listing. We only want the first one. */ $match = $matches[0]; /* * If the section symbol prefixes this match, hack it off. */ if (substr($match, 0, strlen(SECTION_SYMBOL)) == SECTION_SYMBOL) { $match = substr($match, strlen(SECTION_SYMBOL . ' ')); } /* * Create an instance of the Law class. */ $law = new Law(array('db' => $this->db)); /* * Get the law, so we can get the proper url. */ $laws = $law->get_matching_sections($match, $this->edition_id); /* * If this isn't a valid section number, then just return the match verbatim -- there's no * link to be provided. */ if ($laws === FALSE) { return $matches[0]; } else { $permalink_obj = new Permalink(array('db' => $this->db)); /* * If we have a single law, we just link to it. */ if (count($laws) == 1) { $law = $laws[0]; return '<a class="law" title="' . $law->catch_line . '" href="' . $law->url . '">' . $matches[0] . '</a>'; } elseif (count($laws) > 0) { static $ref_counter; if (!isset($ref_counter)) { $ref_counter = 0; } $ref_counter++; /* * Show a popup listing all possible matches. Pass this data as * JSON to make jquery able to handle it natively. */ $popup_content = str_replace("'", "'", json_encode($laws)); $return_text = '<a class="law multiple-references" title="This section number matches multiple sections." data-popup-content=\'' . $popup_content . '\' data-ref-count="' . $ref_counter . '" >' . $matches[0] . '</a>'; return $return_text; } } }