/** * Retrieve all of the material relevant to a given law. */ function get_law() { /* * We're going to need access to the database connection throughout this class. */ global $db; /* * 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) || $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_related_laws = 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, 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 = $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 = $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(); /* * 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 ($this->config->get_tags == TRUE) { $sql = 'SELECT text FROM tags WHERE law_id = ' . $db->quote($this->section_id); $result = $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. */ if (isset($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; } } } } /* * 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(); } /* * Gather all laws that are textually similar to this law. */ if ($this->config->get_related_laws == TRUE) { //$this->metadata = Law::get_related(); } /* * 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 = $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->json = 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; }
/** * Get a list of defined terms for a given structural unit of the code, returning just a listing * of terms. (The idea is that we can use an Ajax call to get each definition on demand.) */ function term_list() { /* * We're going to need access to the database connection throughout this class. */ global $db; /* * If a structural ID hasn't been passed to this function, then return a listing of terms * that apply to the entirety of the code. */ if (!isset($this->structure_id) && !isset($this->scope)) { $this->scope = 'global'; } /* * If we haven't specified whether we want to include generic terms * in this query, include them by default. */ if (!isset($this->generic_terms)) { $this->generic_terms = TRUE; } /* * Create an object in which we'll store terms that are identified. */ $terms = new stdClass(); /* * Get a listing of all structural units that contain the current structural unit -- that is, * if this is a chapter, get the ID of both the chapter and the title. And so on. */ if (isset($this->structure_id)) { $heritage = new Structure(); $heritage->id = $this->structure_id; $ancestry = $heritage->id_ancestry(); $tmp = array(); foreach ($ancestry as $level) { $tmp[] = $level->id; } $ancestry = $tmp; unset($tmp); } /* * Get a list of all globally scoped terms. */ $sql_args = array(':global_scope' => 'global'); if (isset($this->scope) && $this->scope == 'global') { $sql = 'SELECT dictionary.term FROM dictionary LEFT JOIN laws ON dictionary.law_id=laws.id WHERE scope = :global_scope'; } else { $sql = 'SELECT DISTINCT dictionary.term FROM dictionary LEFT JOIN laws ON dictionary.law_id=laws.id LEFT JOIN structure ON laws.structure_id=structure.id WHERE ( (dictionary.law_id=:section_id) AND (dictionary.scope=:section_scope) )'; $sql_args[':section_id'] = $this->section_id; $sql_args[':section_scope'] = 'section'; $ancestry_count = count($ancestry); for ($i = 0; $i < $ancestry_count; $i++) { $sql .= " OR (dictionary.structure_id=:structure{$i})"; $sql_args[":structure{$i}"] = $ancestry[$i]; } $sql .= ' OR (scope=:global_scope)'; } $statement = $db->prepare($sql); $result = $statement->execute($sql_args); /* * Establish the counter we'll use as our object numbering scheme throughout both of our * queries. */ $i = 0; /* * If any terms are found, then add them to our $terms object. */ if ($statement->rowCount() > 1) { /* * Build up the result as an object as we loop through the results. */ while ($term = $statement->fetch(PDO::FETCH_OBJ)) { $terms->{$i} = $term->term; $i++; } } /* * Assemble a second query, this one against our generic legal dictionary, but only if we * have opted to include generic terms. */ if ($this->generic_terms === TRUE) { $sql = 'SELECT term FROM dictionary_general'; $sql_args = null; $statement = $db->prepare($sql); $result = $statement->execute($sql_args); if ($result !== FALSE && $statement->rowCount() > 0) { /* * Append these results to the existing $terms object, continuing to use the previously- * defined $i counter. */ while ($term = $statement->fetch(PDO::FETCH_OBJ)) { $terms->{$i} = $term->term; $i++; } } } $tmp = (array) $terms; $tmp = array_unique($tmp); $terms = (object) $tmp; return $terms; }