/** * 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; }
/** * Recurse through structural information * * A helper method for structural_stats_generate(); not intended to be called on its own. */ function structural_stats_recurse() { /* * Retrieve basic stats about the children of this structural unit. */ $struct = new Structure(); $struct->id = $this->structure_id; $child_structures = $struct->list_children(); $child_laws = $struct->list_laws(); /* * Append the structure's ID to the structural ancestry. */ $this->ancestry[] = $this->structure_id; /* * Store the tallies. */ $this->stats->{$this->structure_id} = new stdClass(); if ($child_structures !== FALSE) { $this->stats->{$this->structure_id}->child_structures = count((array) $child_structures); } if ($child_laws !== FALSE) { $this->stats->{$this->structure_id}->child_laws = count((array) $child_laws); } $this->stats->{$this->structure_id}->depth = $this->depth; $this->stats->{$this->structure_id}->ancestry = $this->ancestry; /* * If this structural unit has child structural units of its own, recurse into those. */ if (isset($this->stats->{$this->structure_id}->child_structures) && $this->stats->{$this->structure_id}->child_structures > 0) { foreach ($child_structures as $child_structure) { $this->depth++; $this->structure_id = $child_structure->id; $this->structural_stats_recurse(); } } /* * Having just finished a recursion, we can remove the last member of the ancestry array * and eliminate one level of the depth tracking. */ $this->ancestry = array_slice($this->ancestry, 0, -1); $this->depth--; }
<dd class="' . $row_class . '"><a href="' . $child->url . '" data-identifier="' . $child->token . '" data-api-url="' . $api_url . '" >' . $child->name . '</a></dd>'; $counter++; } $body .= '</dl>'; } /* * Reset counter */ $counter = 0; /* * Get a listing of all laws that are children of this portion of the structure. */ $laws = $struct->list_laws(); /* * If we have successfully gotten a list of laws, display them. */ if ($laws !== FALSE) { $body .= ' It’s comprised of the following ' . count((array) $laws) . ' sections.</p>'; $body .= '<dl class="title-list laws">'; foreach ($laws as $law) { /* * The remainder of the count divided by the number of classes * yields the proper index for the row class. */ $class_index = $counter % count($row_classes); $row_class = $row_classes[$class_index]; $body .= ' <dt class="' . $row_class . '"><a href="' . $law->url . '">' . SECTION_SYMBOL . ' ' . $law->section_number . '</a></dt>
function handle($args) { /* * If the request is for the structural units sorted by a specific criteria. */ if (isset($_GET['sort'])) { /* * Explicitly reassign the external value to an internal one, for safety's sake. */ if ($_GET['sort'] == 'views') { $order_by = filter_var($_GET['sort'], FILTER_SANITIZE_STRING); } } /* * Create a new instance of the class that handles information about individual laws. */ $struct = new Structure(); /* * Get the structure based on our identifier. */ if ($args['relational_id']) { $struct->structure_id = $args['relational_id']; } else { $struct->structure_id = ''; } $struct->get_current(); $response = $struct->structure; /* * If this structural element does not exist. */ if ($response === FALSE) { $this->handleNotFound(); } /* * List all child structural units. */ $struct->order_by = $order_by; $response->children = $struct->list_children(); /* * List all laws. */ $response->laws = $struct->list_laws(); /* * 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'); }