<?php
#BEGIN_LICENSE
#-------------------------------------------------------------------------
# Module: MAMS (c) 2020-2021 by CMS Made Simple Foundation
#  An add-on module for CMS Made Simple to provide useful functions
#  and commonly used gui capabilities to other modules.
#-------------------------------------------------------------------------
# A fork of:
#
# Module: FrontEndUsers (c) 2008-2014 by Robert Campbell
#         (calguy1000@cmsmadesimple.org)
#
#-------------------------------------------------------------------------
#
# CMSMS - CMS Made Simple is (c) 2006 - 2021 by CMS Made Simple Foundation
# CMSMS - CMS Made Simple is (c) 2005 by Ted Kulp (wishy@cmsmadesimple.org)
# Visit the CMSMS Homepage at: http://www.cmsmadesimple.org
#
#-------------------------------------------------------------------------
#
# 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 2 of the License, or
# (at your option) any later version.
#
# However, as a special exception to the GPL, this software is distributed
# as an addon module to CMS Made Simple.  You may not use this software
# in any Non GPL version of CMS Made simple, or in any version of CMS
# Made simple that does not indicate clearly and obviously in its admin
# section that the site was built with CMS Made simple.
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Or read it online: http://www.gnu.org/licenses/licenses.html#GPL
#
#-------------------------------------------------------------------------
#END_LICENSE

namespace MAMS\Commands;
use CMSMS\CLI\App;
use CMSMS\CLI\GetOptExt\Command;
use CMSMS\CLI\GetOptExt\Option;
use CMSMS\CLI\GetOptExt\GetOpt;
use GetOpt\Operand;
use mams_user_query;
use mams_user_query_opt;

class UserListCommand extends Command
{
    public function __construct( App $app )
    {
        parent::__construct( $app, 'mams-user-list' );
        $this->addOperand( new Operand( 'pattern', Operand::OPTIONAL ) );
        $this->addOption( Option::Create('g','group')->setDescription('Filter by members of the named group') );
        $this->addOption( Option::Create('l','limit')->setDescription('Page limit (default 500)') );
        $this->addOption( Option::Create('o','offset')->setDescription('Start index (default 0)') );
        $this->addOption( Option::Create('j','json')->setDescription('Output data in JSON format') );
        $this->AddOption( Option::Create(null,'loggedin')->setDescription('Display only loggedin users') );
        $this->AddOption( Option::Create(null,'expired')->setDescription('Display only loggedin users') );
        $this->AddOption( Option::Create(null,'disabled')->setDescription('Display only disabled users') );
        $this->AddOption( Option::Create(null,'created-before')->setDescription('Filter on users created before the specified date') );
        $this->AddOption( Option::Create(null,'created-after')->setDescription('Filter on users created after the specified date') );
        $help = <<<EOT
Sorting of the output.   Possible values are: CREATED_DESC*, CREATED_ASC, USERNAME_ASC, USERNAME_DESC, EXPIRES_ASC, EXPIRES_DESC
EOT;
        $this->AddOption( Option::Create(null,'sortby')->setDescription($help)->setDefaultValue('CREATED_DESC') );
    }

    public function getShortDescription()
    {
        return 'List FEU users';
    }

    public function getLongDescription()
    {
        return 'This command will return a list of FEU users filtered by various criteria';
    }

    protected function normal_output( array $row )
    {
        $fmt = "%-8d %-40s\n";
        printf($fmt,$row['id'],$row['username']);
    }

    public function handle()
    {
        $pattern = trim($this->getOperand('pattern')->value());
        $group = $this->getOption('group')->value();
        $limit = (int) $this->GetOption('limit')->value();
        if( $limit < 1 ) $limit = 500;
        $limit = min(100000,500);
        $offset = (int) $this->GetOption('offset')->value();
        $offset = max($offset,0);
        $loggedin = (int) $this->GetOption('loggedin')->value();
        $disabled = (int) $this->GetOption('disabled')->value();
        $expired = (int) $this->GetOption('expired')->value();
        $created_before = trim($this->GetOption('created-before'));
        $created_after = trim($this->GetOption('created-after'));
        $json = $this->GetOption('json')->value();

        $query = new mams_user_query;
        $query->set_pagelimit($limit);
        $query->set_offset($offset);
        if( $pattern ) $query->add_and_opt( mams_user_query_opt::MATCH_USERNAME, $pattern );
        if( !is_null($group) ) $query->add_and_opt( mams_user_query_opt::MATCH_GROUP, $group );
        if( $loggedin !== 0 ) $query->add_and_opt( mams_user_query_opt::MATCH_LOGGEDIN );
        if( $expired !== 0 ) $query->add_and_opt( mams_user_query_opt::MATCH_EXPIRES_LT, time() );
        if( $disabled !== 0 ) $query->add_and_opt( mams_user_query_opt::MATCH_DISABLED );
        if( $created_before ) {
            $ts = strtotime($created_before);
            if( !$ts ) throw new \LogicException("Could not convert $ts to a valid time value... see strtotime");
            $query->add_and_opt( mams_user_query_opt::MATCH_CREATED_LT, $ts );
        }
        if( $created_after ) {
            $ts = strtotime($created_after);
            if( !$ts ) throw new \LogicException("Could not convert $ts to a valid time value... see strtotime");
            $query->add_and_opt( mams_user_query_opt::MATCH_CREATED_GE, $ts );
        }

        $sortby = $this->GetOption('sortby')->value();
        if( !$sortby ) $sortby = 'CREATED_DESC';
        switch( strtoupper($sortby) ) {
        case 'CREATED_ASC':
            $query->set_sortby( $query::RESULT_SORTBY_CREATED );
            $query->set_sortorder( $query::RESULT_SORTORDER_ASC );
            break;
        case 'CREATED_DESC':
            $query->set_sortby( $query::RESULT_SORTBY_CREATED );
            $query->set_sortorder( $query::RESULT_SORTORDER_DESC );
            break;
        case 'USERNAME_ASC':
            $query->set_sortby( $query::RESULT_SORTBY_USERNAME );
            $query->set_sortorder( $query::RESULT_SORTORDER_ASC );
            break;
        case 'USERNAME_DESC':
            $query->set_sortby( $query::RESULT_SORTBY_USERNAME );
            $query->set_sortorder( $query::RESULT_SORTORDER_DESC );
            break;
        case 'EXPIRES_ASC':
            $query->set_sortby( $query::RESULT_SORTBY_EXPIRES );
            $query->set_sortorder( $query::RESULT_SORTORDER_ASC );
            break;
        case 'EXPIRES_DESC':
            $query->set_sortby( $query::RESULT_SORTBY_EXPIRES );
            $query->set_sortorder( $query::RESULT_SORTORDER_DESC );
            break;
        default:
            throw new \InvalidArgumentException("$sortby is not a valid sort option");
        }

        $fix_row = function($row) {
            $row['id'] = (int) $row['id'];
            $row['nonstd'] = (int) $row['nonstd'];
            $row['disabled'] = (int) $row['disabled'];
            $row['force_newpw'] = (int) $row['force_newpw'];
            $row['force_chsettings'] = (int) $row['force_chsettings'];
            $row['must_validate'] = (int) $row['must_validate'];
            $row['loggedin'] = (int) $row['loggedin'];
            unset($row['salt']);
            return $row;
        };

        $rs = $query->execute();
        if( $json ) {
            $out = null;
            while( !$rs->EOF() ) {
                $row = $rs->fields;
                $out[] = $fix_row($row);
                $rs->MoveNext();
            }
            echo json_encode($out,JSON_PRETTY_PRINT);
            return;
        }

        while( !$rs->EOF() ) {

            $this->normal_output( $rs->fields );
            $rs->MoveNext();
        }
        exit();
    }
} // end of class.
