/**
  * 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;
 }
Example #2
0
 * 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.
 */
if (isset($law->citation) && is_object($law->citation)) {
    $sidebar .= '<section class="related-group grid-box" id="cite-as">
    /**
     * 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;
    }
    /**
     * 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;
    }
 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 #6
0
 * @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.
 */
$laws->record_view();
/*
 * If this is a request for a plain text version of this law, simply display that and exit.
 */
if (isset($_GET['plain_text'])) {
    /*
     * Instruct the browser that this is plain text.
     */
 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;
     }
 }
 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']);
 }
 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 #10
0
    } 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;
            } else {
                $body .= $law->catch_line;
            }