<?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 UserAddCommand extends Command
{
    public function __construct( App $app )
    {
        parent::__construct( $app, 'mams-user-add' );
        $this->addOperand( new Operand( 'username', Operand::REQUIRED ) );
        $this->addOperand( new Operand( 'password', Operand::REQUIRED ) );
        $this->addOperand( new Operand( 'group', Operand::MULTIPLE ) );
        $this->addOption( Option::Create('p','prop', GetOpt::MULTIPLE_ARGUMENT)->setDescription('A user property in the form of name=value') );
        $this->addOption( Option::Create('f','force')->setDescription('Ignore email address checks, and allow specifying unknown properties'));
    }

    public function getShortDescription()
    {
        return 'Add a new FEU User account';
    }

    public function getLongDescription()
    {
        return 'Add a new FEU user to one or more groups';
    }

    public function handle()
    {
        $username = trim($this->getOperand('username')->value());
        $password = trim($this->getOperand('password')->value());
        $groups = $this->getOperand('group')->value();
        $props = $this->getOption('prop')->value();
        $force = $this->getOption('force')->value();
        if( empty($groups) ) throw new \RuntimeException('Please specify one or more group names');

        // now validate the groups
        $mams = \cms_utils::get_module(MOD_MAMS);
        $defns = $mams->GetPropertyDefns();
        $allgroups = $mams->GetGroupList();

        // validate that the username does not already exist
        $test_uid = $mams->GetUserID($username);
        if( $test_uid > 0 ) throw new \RuntimeException('The username '.$username.' already exists');
        if( !$force && $mams->GetPreference('username_is_email') && !is_email($username) ) {
            throw new \RuntimeException($username.' is not a valid email address');
        }

        // validate the specified group names.
        $groupnames = array_keys($allgroups);
        $err_groups = array_diff($groups, $groupnames);
        if( !empty($err_groups) ) throw new \RuntimeException('One or more groups specified does not exist');

        // get all of the properties for each of these groups
        $allprops = [];
        foreach( $groups as $group ) {
            $gid = $allgroups[$group];
            $relns = $mams->GetGroupPropertyRelations($gid);
            $allprops = \MAMS\RRUtils::array_merge_by_name_required($allprops,$relns);
            usort($allprops, array('xt_array','compare_elements_by_sortorder_key'));
        }

        // get a list of the properties that are allowed
        //   (not of type data)
        $allowed_props = array_filter($allprops, function($item) use ($defns, $mams){
                $name = $item['name'];
                if( !isset($defns[$name]) ) return;
                if( $defns[$name]['type'] == $mams::FIELDTYPE_DATA ) return;
                if( $defns[$name]['type'] == $mams::FIELDTYPE_IMAGE ) return;
                return TRUE;
            });
        $allowed_props = array_map(function($item){
                return $item['name'];
            }, $allowed_props);

        // now get all of our required properties
        $required = array_filter($allprops,function($item){
                return $item['required'] == 2;
            });
        $required = array_map(function($item){
                return $item['name'];
            }, $required);

        // now parse our property options
        $gather_props = function($props) {
            $out = [];
            if( is_array($props) ) {
                foreach( $props as $prop_opt ) {
                    list($prop_name,$value) = explode('=',$prop_opt,2);
                    $prop_name = trim($prop_name);
                    $value = trim($value);
                    if( $prop_name ) {
                        $out[$prop_name] = $value;
                    }
                }
            }
            return $out;
        };

        // now, see if we have any of these props
        $valid_props = $gather_props($props);
        $prop_keys = array_keys($valid_props);

        // if we have required properties, make sure they were all specified.
        if( !empty($required)) {
            if( !empty(array_diff($required,$prop_keys)) ) throw new \RuntimeException("The following properties are required according to the groups specified: ".implode(',',$required));
        }

        // make sure all of our properties are known.
        $not_allowed = array_diff($prop_keys,$allowed_props);
        if( !empty($not_allowed) ) throw new \RuntimeException('The following properties do not exist: '.implode($not_allowed));

        // add the user
        $tmp = (int) $mams->GetPreference('expireage_months',520);
        $expires = strtotime("+{$tmp} months 00:00");
        if( !$expires ) $expires = PHP_INT_MAX;

        $res = $mams->AddUser( $username, $password, $expires );
        if( !is_array($res) || !isset($res[0]) || !$res[0] ) throw new \RuntimeException('Could not create user: '.$res[1]);;
        $uid = $res[1];

        // add him to his groups
        foreach( $groups as $group ) {
            $gid = $allgroups[$group];
            $res = $mams->AddUserToGroup( $uid, $gid );
            if( !$res ) throw new \RuntimeException('Problem adding user to group... creation incomplete');
        }

        // set properties
        if( $valid_props ) {
            foreach( $valid_props as $prop_name => $value ) {
                $res = $mams->SetUserPropertyFull($prop_name,$value,$uid);
                if( !$res ) throw new \RuntimeException('Problem setting user properties... creation incomplete');
            }
        }

        // and done.
    }

} // end of class.
