Last commit for bin/code_tool.php: 9ff742e4cc2ef0dba312dd0c5f642890b6945730

First pass at converting files to use autoloading! Take care if you have an old yioop system you are upgrading, a=chris

Chris Pollett [2015-07-01 02:Jul:st]
First pass at converting files to use autoloading! Take care if you have an old yioop system you are upgrading, a=chris
<?php
/**
 *  SeekQuarry/Yioop --
 *  Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 *  Copyright (C) 2009 - 2012  Chris Pollett chris@pollett.org
 *
 *  LICENSE:
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  END LICENSE
 *
 * Tool used to help coding with Yioop. Has commands to update copyright info,
 * clean trailing spaces, find long lines, and do global file searches and
 * replaces.
 *
 * @author Chris Pollett chris@pollett.org
 * @package seek_quarry
 * @subpackage bin
 * @license http://www.gnu.org/licenses/ GPL3
 * @link http://www.seekquarry.com/
 * @copyright 2009 - 2012
 * @filesource
 */

if(php_sapi_name() != 'cli') {echo "BAD REQUEST"; exit();}

/** Calculate base directory of script @ignore */
define("BASE_DIR", substr(
    dirname(realpath($_SERVER['PHP_SELF'])), 0,
    -strlen("/bin")));

/** Load in global configuration settings */
require_once BASE_DIR.'/configs/config.php';
if(!PROFILE) {
    echo "Please configure the search engine instance by visiting" .
        "its web interface on localhost.\n";
    exit();
}

/** Used to get @see traverseDirectory() */
require_once BASE_DIR.'/models/model.php';

/** Used to get @see readInput() */
require_once BASE_DIR.'/lib/utility.php';
/*
 *  We'll set up multi-byte string handling to use UTF-8
 */
mb_internal_encoding("UTF-8");
mb_regex_encoding("UTF-8");

$no_instructions = false;
$model = new Model();
$db = $model->db;

$commands = array("copyright", "clean", "longlines", "search", "replace");
$change_extensions = array("php", "js", "ini", "css", "thtml", "xml");
$exclude_paths_containing = array("/.", "/extensions/");
$num_spaces_tab = 4;

if(isset($argv[1]) && in_array($argv[1], $commands)) {
    $command = $argv[1];
    array_shift($argv);
    array_shift($argv);
    $no_instructions = $command($argv);
}


if(!$no_instructions) {
    echo <<< EOD
code_tool.php has the following command formats:

php code_tool.php clean path
    Replaces all tabs with four spaces and trims all whitespace off ends of
    lines in the folder or file path.

php code_tool.php copyright path
    Adjusts all lines in the files in the folder at path (or if
    path is a file just that) of the form 2009 - \d\d\d\d to
    the form 2009 - this_year where this_year is the current year.

php code_tool.php longlines path
    Prints out all lines in files in the folder or file path which are
    longer than 80 characters.

php code_tool.php replace path pattern replace_string
  or
php code_tool.php replace path pattern replace_string effect
    Prints all lines matching the regular expression pattern followed
    by the result of replacing pattern with replace_string in the
    folder or file path. Does not change files.

php code_tool.php replace path pattern replace_string interactive
    Prints each line matching the regular expression pattern followed
    by the result of replacing pattern with replace_string in the
    folder or file path. Then it asks if you want to update the line.
    Lines you choose for updating will be modified in the files.

php code_tool.php replace path pattern replace_string change
    Each line matching the regular expression pattern is update
    by replacing pattern with replace_string in the
    folder or file path. This format doe not echo anything, it does a global
    replace without interaction.

php code_tool.php search path pattern
    Prints all lines matching the regular expression pattern in the
    folder or file path.

EOD;
}

/**
 *
 * @param array $args $args[0] contains path to sub-folder/file
 * @return bool $no_instructions false if should output code_tool.php
 *      instructions
 */
function clean($args)
{
    global $num_spaces_tab;

    $no_instructions = false;
    if(isset($args[0])) {
        $path = realpath($args[0]);
        $no_instructions = true;
        mapPath($path, "cleanLinesFile");
    }
    return $no_instructions;
}

/**
 * Updates the copyright info (assuming in Yioop docs format) on files
 * in supplied sub-folder/file. That is, it changes strings matching
 * /2009 - \d\d\d\d/ to 2009 - current_year in those files/file.
 *
 * @param array $args $args[0] contains path to sub-folder/file
 * @return bool $no_instructions false if should output code_tool.php
 *      instructions
 */
function copyright($args)
{
    $no_instructions = false;

    if(isset($args[0])) {
        $path = realpath($args[0]);
        $year = date("Y");
        $out_year = "2009 - ".$year;
        replaceFile("", "/2009 \- \d\d\d\d/", $out_year, "change");
            // initialize callback
        mapPath($path, "replaceFile");
        $no_instructions = true;
    }
    return $no_instructions;
}



/**
 * Search and echos line numbers and lines for lines of length greater than 80
 * characters in files in supplied sub-folder/file,
 *
 * @param array $args $args[0] contains path to sub-folder/file
 * @return bool $no_instructions false if should output code_tool.php
 *      instructions
 */
function longlines($args)
{
    global $change_extensions;
    $no_instructions = false;
    $change_extensions = array_diff($change_extensions, array("ini", "xml"));

    if(isset($args[0])) {
        $path = realpath($args[0]);
        searchFile("", "/([^\n]){81}/");// initialize callback
        mapPath($path, "searchFile");
        $no_instructions = true;
    }
    return $no_instructions;
}

/**
 * Performs a search and replace for given pattern in files in supplied
 * sub-folder/file
 *
 * @param array $args $args[0] contains path to sub-folder/file,
 *      $args[1] contains the regex searching for, $args[2] contains
 *      what it should be replaced with, $args[3] (defaults to effect)
 *      controls the mode of operation. One of "effect", "change", or
 *      "interactive". effect shows line number and lines matching pattern,
 *      but commits no changes; interactive for each match, prompts user
 *      if should do the change, change does a global search and replace
 *      without output
 * @return bool $no_instructions false if should output code_tool.php
 *      instructions
 */
function replace($args)
{
    $no_instructions = false;

    if(isset($args[0]) && isset($args[1]) && isset($args[2])) {
        $path = realpath($args[0]);
        $no_instructions = true;
        $pattern = $args[1];
        $replace = $args[2];
        $mode = (isset($args[3])) ? $args[3] : "effect";
        if(strlen(stristr($pattern, "@")) > 0) {
            echo "Search pattern should not contain @, bailing !!!";
            return false;
        }
        $len = strlen($pattern);
        if($len >= 2) {
            if($pattern[0] != $pattern[$len - 1]) {
                $pattern = "@$pattern@";
            }
            replaceFile("", $pattern, $replace, $mode); // initialize callback

            mapPath($path, "replaceFile");
        }
    }
    return $no_instructions;
}

/**
 * Performs a search for given pattern in files in supplied sub-folder/file
 *
 * @param array $args $args[0] contains path to sub-folder/file,
 *      $args[1] contains the regex searching for
 * @return bool $no_instructions false if should output code_tool.php
 *      instructions
 */
function search($args)
{
    $no_instructions = false;

    if(isset($args[0]) && isset($args[1])) {
        $path = realpath($args[0]);
        $no_instructions = true;
        $pattern = $args[1];
        $len = strlen($pattern);
        if(strlen(stristr($pattern, "@")) > 0) {
            echo "Search pattern should not contain @, bailing !!!";
            return false;
        }
        if($len >= 2) {
            if($pattern[0] != $pattern[$len - 1]) {
                $pattern = "@$pattern@";
            }
            searchFile("", $pattern); // initialize callback
            mapPath($path, "searchFile");
        }
    }
    return $no_instructions;
}

/**
 * Callback function applied to each file in the directory being traversed
 * by @see copyright(). It checks if the files is of the extension of a code file
 * and if so trims whitespace from its lines and then updates the lines
 * of the form 2009 - \d\d\d\d to the supplied copyright year
 *
 * @param string $filename name of file to check for copyright lines and updated
 */
function changeCopyrightFile($filename, $set_year = false)
{
    global $change_extensions;
    static $year = 2012;

    if($set_year) {
        $year = $set_year;
    }

    $path_parts = pathinfo($filename);
    $extension = $path_parts['extension'];
    if(!excludedPath($filename) && in_array($extension, $change_extensions)) {
        $lines = file($filename);
        $out_lines = array();
        $num_lines = count($lines);

        $change = false;
        foreach($lines as $line) {
            $new_line = preg_replace("/2009 \- \d\d\d\d/", $out_year,
                $line);
            $out_lines[] = $new_line;
            if(strcmp($new_line, $line) != 0) {
                $change = true;
            }
        }
        $out_file = implode("\n", $out_lines);
        if($change) {
            file_put_contents($filename, $out_file);
        }
    }
}

/**
 * Callback function applied to each file in the directory being traversed
 * by @see clean().
 *
 * @param string $filename name of file to clean lines for
 */
function cleanLinesFile($filename)
{
    global $change_extensions;
    global $num_spaces_tab;

    $spaces = str_repeat(" ", $num_spaces_tab);
    $path_parts = pathinfo($filename);
    $extension = $path_parts['extension'];
    if(!excludedPath($filename) && in_array($extension, $change_extensions)) {

        $lines = file($filename);
        $out_lines = array();
        $change = false;
        foreach($lines as $line) {
            $new_line = preg_replace("/\t/", $spaces, $line);
            $new_line = rtrim($new_line);
            $out_lines[] = $new_line;
            if(strcmp($new_line."\n", $line) != 0) {
                $change = true;
            }
        }
        $out_file = implode("\n", $out_lines);
        if($change) {
            file_put_contents($filename, $out_file);
        }
    }
}

/**
 * Callback function applied to each file in the directory being traversed
 * by @see search(). Searches $filename matching $pattern and outputs line
 *      numbers and lines
 *
 * @param string $filename name of file to search in
 * @param mixed $set_pattern if not false, then sets $set_pattern in $pattern to
 *      initialize the callback on subsequent calls. $pattern here is the
 *      search pattern
 */
function searchFile($filename, $set_pattern = false)
{
    global $change_extensions;
    static $pattern = "/";

    if($set_pattern) {
        $pattern = $set_pattern;
    }
    $path_parts = pathinfo($filename);
    if(!isset($path_parts['extension'])) {
        return;
    }
    $extension = $path_parts['extension'];
    if(!excludedPath($filename) && in_array($extension, $change_extensions)) {
        $lines = file($filename);
        $no_output = true;
        $num = 0;
        foreach($lines as $line) {
            $num++;
            if(preg_match($pattern, $line)) {
                if($no_output) {
                    $no_output = false;
                    echo "\nIn $filename:\n";
                }
                echo "  Line $num: $line";
            }
        }
    }
}

/**
 * Callback function applied to each file in the directory being traversed
 * by @see replace(). Searches $filename matching $pattern. Depending
 *      on $mode ($arg[2] as described in replace()), it outputs and
 *      replaces with $replace
 *
 * @param string $filename name of file to search and replace in
 * @param mixed $set_pattern if not false, then sets $set_pattern in $pattern to
 *      initialize the callback on subsequent calls. $pattern here is the
 *      search pattern
 * @param mixed $set_replace if not false, then sets $set_replace in $replace to
 *      initialize the callback on subsequent calls.
 * @param mixed $set_mode if not false, then sets $set_mode in $mode to
 *      initialize the callback on subsequent calls.
 */
function replaceFile($filename, $set_pattern = false,
    $set_replace = false, $set_mode = false)
{
    global $change_extensions;
    static $pattern = "/";
    static $replace = "";
    static $mode = "effect";

    $pattern = ($set_pattern) ? $set_pattern : $pattern;
    $replace = ($set_replace) ? $set_replace : $replace;
    $mode = ($set_mode) ? $set_mode : $mode;

    $path_parts = pathinfo($filename);
    if(!isset($path_parts['extension'])) {
        return;
    }
    $extension = $path_parts['extension'];
    if(!excludedPath($filename) && in_array($extension, $change_extensions)) {
        $lines = file($filename);
        $out_lines = "";
        $no_output = true;
        $silent = false;
        if($mode == "change") {
            $silent = true;
        }
        $num = 0;
        $change = false;
        foreach($lines as $line) {
            $num++;
            $new_line = $line;
            if(preg_match($pattern, $line)) {
                if($no_output && !$silent) {
                    $no_output = false;
                    echo "\nIn $filename:\n";
                }
                $new_line = preg_replace($pattern, $replace, $line);
                if(!$silent) {
                    echo "  Line $num: $line";
                    echo "  Changes to: $new_line";
                }
                if($mode == "interactive") {
                    echo "Do replacement? (Yy - yes, anything else no): ";
                    $confirm = strtolower(readInput());
                    if($confirm != "y") {
                        $new_line = $line;
                    }
                }
                if(strcmp($new_line, $line) != 0) {
                    $change = true;
                }
            }
            $out_lines .= $new_line;
        }
        if(in_array($mode, array("change", "interactive"))) {
            if($change) {
                file_put_contents($filename, $out_lines);
            }
        }
    }
}

/**
 * Applies the function $callback to each file in $path
 *
 * @param string $path to apply map $callback to
 * @param string $callback function name to call with filename of each file
 *      in path
 */
function mapPath($path, $callback)
{
    global $db;

    if(is_dir($path)) {
        $db->traverseDirectory($path, $callback, true);
    } else {
        $callback($path);
    }
}

/**
 * Checks if $path is amongst a list of paths which should be ignored
 *
 * @param $path a directory path
 * @return bool whether or not it should be ignored (true == ignore)
 */
function excludedPath($path)
{
    global $exclude_paths_containing;

    foreach($exclude_paths_containing as $exclude) {
        if(strstr($path, $exclude)) {
            return true;
        }
    }

    return false;
}
?>
ViewGit