Example #1
0
 function delete($id = FALSE)
 {
     if ($id) {
         $law = new Law($id);
         $law->delete();
         set_notify('success', lang('delete_data_complete'));
     }
     redirect($_SERVER['HTTP_REFERER']);
 }
Example #2
0
			</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 . '&nbsp;<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');
 }
Example #4
0
 /**
  * Returns count of tag's laws
  * @return int
  */
 public function getLawCount()
 {
     return Law::find()->where(['tagYes' => $this->name])->orWhere(['tagNo' => $this->name])->count();
 }
Example #5
0
<?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;
    }
Example #8
0
        } 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']);
 }
Example #10
0
 /**
  * @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');
 }
Example #12
0
    } 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 . '&nbsp;' . $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("'", "&#39;", 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;
            }
        }
    }