<commit_before><?php
/**
 * @copyright Copyright (c) 2017 <NAME> <<EMAIL>>
 *
 * @author <NAME> <<EMAIL>>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

namespace OCA\User_LDAP\Jobs;

use OC\BackgroundJob\TimedJob;
use OC\ServerNotAvailableException;
use OCA\User_LDAP\Access;
use OCA\User_LDAP\AccessFactory;
use OCA\User_LDAP\Configuration;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\ConnectionFactory;
use OCA\User_LDAP\FilesystemHelper;
use OCA\User_LDAP\Helper;
use OCA\User_LDAP\LDAP;
use OCA\User_LDAP\LogWrapper;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\User\Manager;
use OCP\IAvatarManager;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Image;
use OCP\IUserManager;
use OCP\Notification\IManager;

class Sync extends TimedJob {
	const MAX_INTERVAL = 12 * 60 * 60; // 12h
	const MIN_INTERVAL = 30 * 60; // 30min
	/** @var  Helper */
	protected $ldapHelper;
	/** @var  LDAP */
	protected $ldap;
	/** @var  Manager */
	protected $userManager;
	/** @var UserMapping */
	protected $mapper;
	/** @var  IConfig */
	protected $config;
	/** @var  IAvatarManager */
	protected $avatarManager;
	/** @var  IDBConnection */
	protected $dbc;
	/** @var  IUserManager */
	protected $ncUserManager;
	/** @var  IManager */
	protected $notificationManager;
	/** @var ConnectionFactory */
	protected $connectionFactory;
	/** @var AccessFactory */
	protected $accessFactory;

	public function __construct() {
		$this->setInterval(
			\OC::$server->getConfig()->getAppValue(
				'user_ldap',
				'background_sync_interval',
				self::MIN_INTERVAL
			)
		);
	}

	/**
	 * updates the interval
	 *
	 * the idea is to adjust the interval depending on the amount of known users
	 * and the attempt to update each user one day. At most it would run every
	 * 30 minutes, and at least every 12 hours.
	 */
	public function updateInterval() {
		$minPagingSize = $this->getMinPagingSize();
		$mappedUsers = $this->mapper->count();

		$runsPerDay = ($minPagingSize === 0 || $mappedUsers === 0) ? self::MAX_INTERVAL
			: $mappedUsers / $minPagingSize;
		$interval = floor(24 * 60 * 60 / $runsPerDay);
		$interval = min(max($interval, self::MIN_INTERVAL), self::MAX_INTERVAL);

		$this->config->setAppValue('user_ldap', 'background_sync_interval', $interval);
	}

	/**
	 * returns the smallest configured paging size
	 * @return int
	 */
	protected function getMinPagingSize() {
		$configKeys = $this->config->getAppKeys('user_ldap');
		$configKeys = array_filter($configKeys, function($key) {
			return strpos($key, 'ldap_paging_size') !== false;
		});
		$minPagingSize = null;
		foreach ($configKeys as $configKey) {
			$pagingSize = $this->config->getAppValue('user_ldap', $configKey, $minPagingSize);
			$minPagingSize = $minPagingSize === null ? $pagingSize : min($minPagingSize, $pagingSize);
		}
		return (int)$minPagingSize;
	}

	/**
	 * @param array $argument
	 */
	public function run($argument) {
		$this->setArgument($argument);

		$isBackgroundJobModeAjax = $this->config
				->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'ajax';
		if($isBackgroundJobModeAjax) {
			return;
		}

		$cycleData = $this->getCycle();
		if($cycleData === null) {
			$cycleData = $this->determineNextCycle();
			if($cycleData === null) {
				$this->updateInterval();
				return;
			}
		}

		if(!$this->qualifiesToRun($cycleData)) {
			$this->updateInterval();
			return;
		}

		try {
			$expectMoreResults = $this->runCycle($cycleData);
			if ($expectMoreResults) {
				$this->increaseOffset($cycleData);
			} else {
				$this->determineNextCycle();
			}
			$this->updateInterval();
		} catch (ServerNotAvailableException $e) {
			$this->determineNextCycle();
		}
	}

	/**
	 * @param array $cycleData
	 * @return bool whether more results are expected from the same configuration
	 */
	public function runCycle($cycleData) {
		$connection = $this->connectionFactory->get($cycleData['prefix']);
		$access = $this->accessFactory->get($connection);
		$access->setUserMapper($this->mapper);

		$filter = $access->combineFilterWithAnd(array(
			$access->connection->ldapUserFilter,
			$access->connection->ldapUserDisplayName . '=*',<commit_msg>fix changing to next cycle<commit_after><?php
/**
 * @copyright Copyright (c) 2017 <NAME> <<EMAIL>>
 *
 * @author <NAME> <<EMAIL>>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

namespace OCA\User_LDAP\Jobs;

use OC\BackgroundJob\TimedJob;
use OC\ServerNotAvailableException;
use OCA\User_LDAP\Access;
use OCA\User_LDAP\AccessFactory;
use OCA\User_LDAP\Configuration;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\ConnectionFactory;
use OCA\User_LDAP\FilesystemHelper;
use OCA\User_LDAP\Helper;
use OCA\User_LDAP\LDAP;
use OCA\User_LDAP\LogWrapper;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\User\Manager;
use OCP\IAvatarManager;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Image;
use OCP\IUserManager;
use OCP\Notification\IManager;

class Sync extends TimedJob {
	const MAX_INTERVAL = 12 * 60 * 60; // 12h
	const MIN_INTERVAL = 30 * 60; // 30min
	/** @var  Helper */
	protected $ldapHelper;
	/** @var  LDAP */
	protected $ldap;
	/** @var  Manager */
	protected $userManager;
	/** @var UserMapping */
	protected $mapper;
	/** @var  IConfig */
	protected $config;
	/** @var  IAvatarManager */
	protected $avatarManager;
	/** @var  IDBConnection */
	protected $dbc;
	/** @var  IUserManager */
	protected $ncUserManager;
	/** @var  IManager */
	protected $notificationManager;
	/** @var ConnectionFactory */
	protected $connectionFactory;
	/** @var AccessFactory */
	protected $accessFactory;

	public function __construct() {
		$this->setInterval(
			\OC::$server->getConfig()->getAppValue(
				'user_ldap',
				'background_sync_interval',
				self::MIN_INTERVAL
			)
		);
	}

	/**
	 * updates the interval
	 *
	 * the idea is to adjust the interval depending on the amount of known users
	 * and the attempt to update each user one day. At most it would run every
	 * 30 minutes, and at least every 12 hours.
	 */
	public function updateInterval() {
		$minPagingSize = $this->getMinPagingSize();
		$mappedUsers = $this->mapper->count();

		$runsPerDay = ($minPagingSize === 0 || $mappedUsers === 0) ? self::MAX_INTERVAL
			: $mappedUsers / $minPagingSize;
		$interval = floor(24 * 60 * 60 / $runsPerDay);
		$interval = min(max($interval, self::MIN_INTERVAL), self::MAX_INTERVAL);

		$this->config->setAppValue('user_ldap', 'background_sync_interval', $interval);
	}

	/**
	 * returns the smallest configured paging size
	 * @return int
	 */
	protected function getMinPagingSize() {
		$configKeys = $this->config->getAppKeys('user_ldap');
		$configKeys = array_filter($configKeys, function($key) {
			return strpos($key, 'ldap_paging_size') !== false;
		});
		$minPagingSize = null;
		foreach ($configKeys as $configKey) {
			$pagingSize = $this->config->getAppValue('user_ldap', $configKey, $minPagingSize);
			$minPagingSize = $minPagingSize === null ? $pagingSize : min($minPagingSize, $pagingSize);
		}
		return (int)$minPagingSize;
	}

	/**
	 * @param array $argument
	 */
	public function run($argument) {
		$this->setArgument($argument);

		$isBackgroundJobModeAjax = $this->config
				->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'ajax';
		if($isBackgroundJobModeAjax) {
			return;
		}

		$cycleData = $this->getCycle();
		if($cycleData === null) {
			$cycleData = $this->determineNextCycle();
			if($cycleData === null) {
				$this->updateInterval();
				return;
			}
		}

		if(!$this->qualifiesToRun($cycleData)) {
			$this->updateInterval();
			return;
		}

		try {
			$expectMoreResults = $this->runCycle($cycleData);
			if ($expectMoreResults) {
				$this->increaseOffset($cycleData);
			} else {
				$this->determineNextCycle($cycleData);
			}
			$this->updateInterval();
		} catch (ServerNotAvailableException $e) {
			$this->determineNextCycle($cycleData);
		}
	}

	/**
	 * @param array $cycleData
	 * @return bool whether more results are expected from the same configuration
	 */
	public function runCycle($cycleData) {
		$connection = $this->connectionFactory->get($cycleData['prefix']);
		$access = $this->accessFactory->get($connection);
		$access->setUserMapper($this->mapper);

		$filter = $access->combineFilterWithAnd(array(
			$access->connection->ldapUserFilter,
			$access->connection->ldapUserDisplayName . '=*',
{'fraction_non_alphanumeric': 0.13797376846018797, 'fraction_numerical': 0.006609521842404213, 'mean_word_length': 4.226119805720454, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 89, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1860418', 'n_tokens_mistral': 3427, 'n_tokens_neox': 3120, 'n_words': 804}