<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)

  Copyright (C) 2015-2020  FusionDirectory

  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.

  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/

class mixedGroup extends simplePlugin
{
  protected $locks    = [];

  static function plInfo (): array
  {
    return [
      'plShortName'   => _('Posix group'),
      'plDescription' => _('Posix group settings'),
      'plObjectClass' => ['posixGroup'],
      'plObjectType'  => ['ogroup-user'],
      'plPriority'    => 1,

      'plProvidedAcls'  => parent::generatePlProvidedAcls(static::getAttributesInfo())
    ];
  }

  static function getAttributesInfo (): array
  {
    return [
      'main' => [
        'name'  => _('Properties'),
        'attrs' => [
          new BooleanAttribute(
            _('Force GID'), _('Force GID value for this group'),
            'force_id', FALSE
          ),
          new IntAttribute(
            _('GID'), _('GID value for this group'),
            'gidNumber', FALSE,
            0, FALSE, ''
          ),
          new HiddenAttribute(
            'memberUid', FALSE,
            []
          )
        ]
      ],
      'system_trust' => [
        'name'  => _('System trust'),
        'icon'  => 'geticon.php?context=status&icon=locked&size=16',
        'attrs' => [
          new SelectAttribute(
            _('Trust mode'), _('Type of authorization for those hosts'),
            'trustMode', FALSE,
            ['', 'fullaccess', 'byhost'],
            '',
            [_('disabled'), _('full access'), _('allow access to these hosts')]
          ),
          new SystemsAttribute(
            '', _('Only allow this group to connect to this list of hosts'),
            'host', FALSE
          )
        ]
      ]
    ];
  }

  function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE)
  {
    parent::__construct($dn, $object, $parent, $mainTab);

    $this->attributesAccess['trustMode']->setInLdap(FALSE);
    $this->attributesAccess['trustMode']->setManagedAttributes(
      [
        'multiplevalues' => ['notbyhost' => ['','fullaccess']],
        'erase' => [
          'notbyhost' => ['host']
        ]
      ]
    );
    if ((count($this->host) == 1) && ($this->host[0] == '*')) {
      $this->trustMode = 'fullaccess';
    } elseif (count($this->host) > 0) {
      $this->trustMode = 'byhost';
    }

    $this->attributesAccess['gidNumber']->setUnique('whole');
    $this->attributesAccess['force_id']->setInLdap(FALSE);
    $this->attributesAccess['force_id']->setManagedAttributes(
      [
        'disable' => [
          FALSE => [
            'gidNumber',
          ]
        ]
      ]
    );
  }

  function check (): array
  {
    global $config;
    $errors = parent::check();

    /* Check ID's if they are forced by user */
    if ($this->force_id) {
      if ($this->gidNumber < $config->get_cfg_value('minId')) {
        $errors[] = new SimplePluginCheckError(
          $this->attributesAccess['gidNumber'],
          msgPool::toosmall(_('GID'), $config->get_cfg_value('minId'))
        );
      }
    }

    return $errors;
  }

  function resetCopyInfos ()
  {
    parent::resetCopyInfos();

    $this->force_id = FALSE;
    $this->attributesAccess['gidNumber']->setInitialValue("");
    $this->gidNumber = "";
  }

  function prepare_save (): array
  {
    global $config;
    $ldap = $config->get_ldap_link();
    $members    = $this->parent->getBaseObject()->member;
    $memberUid  = [];
    foreach ($members as $dn) {
      $ldap->cat($dn, ['uid','memberUid']);
      $attrs = $ldap->fetch();
      if (isset($attrs['uid'][0])) {
        $memberUid[] = $attrs['uid'][0];
      }
      if (isset($attrs['memberUid'][0])) {
        unset($attrs['memberUid']['count']);
        $memberUid = array_merge_unique($memberUid, $attrs['memberUid']);
      }
    }
    $this->memberUid = $memberUid;

    if (!$this->force_id) {
      /* Handle gidNumber */
      if ($this->attributesAccess['gidNumber']->getInitialValue() != "") {
        $this->gidNumber = $this->attributesAccess['gidNumber']->getInitialValue();
      } else {
        $this->gidNumber = posixAccount::getNextIdLock('gidNumber', $this->dn);
        $this->locks[] = 'gidNumber';
      }
    }

    $errors = parent::prepare_save();
    if (!empty($errors)) {
      return $errors;
    }

    if ($this->trustMode == 'fullaccess') {
      $this->attrs['host'] = ['*'];
    }

    /* Trust accounts */
    if (($this->trustMode != "") && !in_array('hostObject', $this->attrs['objectClass'])) {
      $this->attrs['objectClass'][] = 'hostObject';
    } elseif (($this->trustMode == "") && (($key = array_search('hostObject', $this->attrs['objectClass'])) !== FALSE)) {
      unset($this->attrs['objectClass'][$key]);
    }

    return $errors;
  }

  function save (): array
  {
    $errors = parent::save();

    foreach ($this->locks as $lock) {
      Lock::deleteByObject($lock);
    }
    $this->locks = [];

    return $errors;
  }

  function addUser ($dn, $uid)
  {
    $this->attributesAccess['memberUid']->addValue($dn, ['uid' => [$uid], 'cn' => [$uid]]);
  }

  function removeUser ($uid)
  {
    $this->attributesAccess['memberUid']->searchAndRemove($uid);
  }
}
