#! /usr/local/bin/php
<?php
/**
 * This script does some checking of themes, to make sure images are
 * synchronised across themes.
 *
 * $Horde: horde/scripts/themes_check.php,v 1.3.10.4 2006/01/01 21:29:09 jan Exp $
 *
 * Copyright 2003-2006 The Horde Project (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (LGPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Marko Djukic <marko@oblo.com>
 * @since   Horde 3.0
 */

@define('AUTH_HANDLER', true);
@define('HORDE_BASE', dirname(__FILE__) . '/..');

/* CLI checks and environment setup first. */
require_once HORDE_BASE . '/lib/core.php';
require_once 'Horde/CLI.php';

/* Make sure no one runs this from the web. */
if (!Horde_CLI::runningFromCLI()) {
    exit("Must be run from the command line\n");
}

/* Get any options. */
$simple = false;
$ignore = array();
if (isset($argv)) {
    /* Get rid of the first arg which is the script name. */
    array_shift($argv);
    while ($arg = array_shift($argv)) {
        if ($arg == '--help') {
            print_usage();
        } elseif ($arg == '-s') {
            $simple = true;
        } elseif (strpos($arg, '-i') === 0) {
            list(,$ignore[]) = explode('=', $arg);
            //$ignore[] = $i;
        } else {
            print_usage("Unrecognised option $arg");
        }
    }
}

/* Set up CLI. */
$cli = &new Horde_CLI();

/* Check if at least the registry is avaiable. */
if (!@file_exists(HORDE_BASE . '/config/registry.php')) {
    $cli->writeln($cli->red('No Horde registry file.'));
    exit;
}

//$cli->writeln($cli->green('Reading...'));
require_once HORDE_BASE . '/lib/base.php';

/* Get the apps and start doing checks. */
$apps = $registry->listApps(array('hidden', 'notoolbar', 'active', 'admin'));

/* Get a list of themes. */
$themes = array();
$themes_dir = $registry->get('themesfs', 'horde');
if ($handle = opendir($themes_dir)) {
    while ($file = readdir($handle)) {
        if ($file == '.' || $file == '..' || $file == 'CVS' ||
            $file == '.svn' ||
            !@file_exists("$themes_dir/$file/info.php") ||
            !@file_exists("$themes_dir/$file/graphics")) {
            continue;
        }

        /* Don't bother checking unless the theme explicitly states that
         * icons will be replaced for this application. */
        include "$themes_dir/$file/info.php";
        if (!isset($theme_icons)) {
            continue;
        }

        /* Store the apps and their theme directories. */
        foreach ($theme_icons as $app) {
            $app_themes_dir = $registry->get('themesfs', $app);
            $themes[$app][$file] = "$app_themes_dir/$file/graphics";
        }

        /* Unset this, to make sure it is checked the next time around. */
        unset($theme_icons);
    }
}

foreach ($apps as $app) {
    /* Set up some dirs. */
    $themes_dir = $registry->get('themesfs', $app);
    $horde_theme_dir = $themes_dir . '/horde';
    $horde_icon_dir = $horde_theme_dir . '/graphics';

    /* Sanity check for the directories. */
    if (!@file_exists($horde_theme_dir) || !@file_exists($horde_icon_dir)) {
        continue;
    }

    /* Get a list of all horde images recursively. */
    $horde_icon_list = array();
    readDirRecursively($horde_icon_dir, $horde_icon_dir, $horde_icon_list);

    /* Loop through themes that replace icons and check for differences. */
    foreach ($themes[$app] as $theme => $theme_icon_dir) {
        $theme_icon_list = array();
        readDirRecursively($theme_icon_dir, $theme_icon_dir, $theme_icon_list);

        /* Check for icons that are in the Horde base theme and not in the
         * custom theme. */
        $diff = array_diff($horde_icon_list, $theme_icon_list);
        /* Don't bother reporting anything for themes that have all the horde
         * base icons. */
        if (empty($diff)) {
            continue;
        }

        $cli->writeln($cli->red(sprintf('[%s] "%s" theme missing these icons:',
                                strtoupper($app),
                                $theme)));
        foreach ($diff as $icon) {
            $cli->writeln($icon);
        }

        /* Check if only doing a Horde base theme to custom theme check. Skip
         * the reverse checking if true. */
        if ($simple) {
            continue;
        }

        /* Check for icons that are in the Horde base theme and not in the
         * custom theme. */
        $diff = array_diff($theme_icon_list, $horde_icon_list);
        /* Don't bother reporting anything for themes that don't have any icons
         * more than the base theme. */
        if (empty($diff)) {
            continue;
        }

        $cli->writeln($cli->blue(sprintf('[%s] "%s" theme has these extra icons:',
                                strtoupper($app),
                                $theme)));
        foreach ($diff as $icon) {
            $cli->writeln($icon);
        }
    }
}

$cli->writeln($cli->green('Done.'));
exit;

/**
 * Loops through the directory recursively and stores the found graphics into
 * an array.
 */
function readDirRecursively($path, $basepath, &$list)
{
    global $ignore;

    if ($handle = opendir($path)) {
        while ($file = readdir($handle)) {
            if ($file == '.' || $file == '..' || $file == 'CVS'
                || $file == '.svn') {
                continue;
            }
            if (is_dir("$path/$file")) {
                readDirRecursively("$path/$file", $basepath, $list);
            } else {
                foreach ($ignore as $pattern) {
                    if (preg_match($pattern, $file)) {
                        continue 2;
                    }
                }
                $list[] = substr($path, strlen($basepath)) . "/$file";
            }
        }
        closedir($handle);
    }

}

function print_usage($message = '') {

    if (!empty($message)) {
        print "themes_check.php: $message\n\n";
    }

    print <<<USAGE
Usage: themes_check.php [OPTION]

Possible options:
  -s            Do only a simple check for any Horde base theme graphics that
                are missing from the other themes, and no check of the
                opposite.
  -i=PATTERN    Insert any valid regex pattern to ignore files from being
                checked. You can enter multiple -i options to include multiple
                patterns. For example: -i="/xcf$/ to ignore any original
                GIMP files.

USAGE;
    exit;
}
