<commit_before><?xml version="1.0" ?>
<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification">

<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/">
	<id>Suki:eiu</id>
	<version>1.0</version>

	<file name="$sourcedir/ScheduledTasks.php">
		<operation>
			<search position="end" />
			<add><![CDATA[
/**
 * Send mails to inactive users, also delete them if they haven't logged in since then.
 *
 * Column to_delete hold the current state of the account:
 * 0 normal, up to date user
 * 1 mail has been sent, user starts her/his grace period after mail was sent.
 * 2 User has not been logged and her/his grace period is over, marked for admin deletion. These are the users who will appear on the mods user list.
 * 3 Admin has marked this user for deletion and will be deleted next time the scheduled task is executed.
 * 4 "Untouchable" means the user will not be fetched by the mod even if the account complies with all of the criteria to be marked for deletion.
 * Column inactive_mail holds a different unix timestamp depending on the account current state:
 * 0 if the user is up to date.
 * It will hold the date the mail was sent to the mail queue when the user to_delete column is set to 1. This time is then used to check if their grace period is over or for resetting their status.
 *
 * @return boolean true The code inside the scheduled task was executed.
 */
function scheduled_emailInactiveUsers()
{
	global $smcFunc, $modSettings, $txt, $sourcedir, $mbname;
	global $scripturl;

	// The mod must be enable
	if (empty($modSettings['eiu_enable']))
		return true;

	loadLanguage('emailInactiveUsers');

	// Today is a good day to do stuff don't you think?
	$today = time();

	// Is there any custom message?
	$customMessage = !empty($modSettings['eiu_message']) ? $modSettings['eiu_message'] : $txt['eiu_custom_message'];
	$customSubject = !empty($modSettings['eiu_subject']) ? $modSettings['eiu_subject'] : $txt['eiu_custom_subject'];
	$postLimit = !empty($modSettings['eiu_posts']) ? $modSettings['eiu_posts'] : 5;

	// How many days must the user needs to be inactive to get the mail? lets stay safe here and declare a default value too.
	$inactiveFor = 86400 * (!empty($modSettings['eiu_inactiveFor']) ? $modSettings['eiu_inactiveFor'] : 15);

	// The user hasn't been logged in since the mail was sent huh? how many days are we gonna wait until the account gets deleted?
	$sinceMail = 86400 * (!empty($modSettings['eiu_sinceMail']) ? $modSettings['eiu_sinceMail'] : 15);

	// The groups from which the users will be fetched from.
	$inGroups = !empty($modSettings['eiu_groups']) ? unserialize($modSettings['eiu_groups']) : array();

	// Don't count the main admin group, AKA id_group 1
	if (!empty($inGroups))
		$inGroups = array_diff($inGroups, array(1));

	// We gotta do a nasty thing here, we have to format a "FIND_IN_SET" for each selected group. Thanks to this we need PHP 5.3 or grater...
	if (!empty($inGroups))
		$additionalgroups = array_map(
			function($k) {
				return ' OR FIND_IN_SET('. $k .', additional_groups)';
			}, $inGroups);

	else
		$additionalgroups = false;

	// Right, we got all we need, lets do some expensive queries.
	$request = $smcFunc['db_query']('', '
			SELECT id_member, email_address, inactive_mail, member_name, real_name, last_login
			FROM {db_prefix}members
			WHERE inactive_mail = 0
				AND posts <= {int:postLimit}
				AND last_login < {int:inactiveFor}
				AND date_registered < {int:inactiveFor}
				AND is_activated = 1
				AND to_delete = 0
				AND email_address is NOT NULL
				AND (id_group IN ({array_int:groups})
					OR id_post_group IN ({array_int:groups})
					'. (!empty($additionalgroups) ? implode(' ', $additionalgroups) : ''). ')',
			array(
				'inactiveFor' => $today - $inactiveFor,
				'groups' => $inGroups,
				'postLimit' => $postLimit,
			)
		);

	$messages = array();

	while($row = $smcFunc['db_fetch_assoc']($request))
	{
		// Lets create the message. Replace our wildcards with the actual data.
		$replacements = array(
			'{user_name}' => $row['real_name'],
			'{display_name}' => $row['member_name'],
			'{last_login}' => timeformat($row['last_login']),
			'{forum_name}' => $mbname,
			'{forum_url}' => $scripturl,
		);

		// Split the replacements up into two arrays, for use with str_replace.
		$find = array();
		$replace = array();

		foreach ($replacements as $f => $r)
		{
			$find[] = $f;
			$replace[] = $r;
		}

		$messages[$row['id_member']] = array(
			'message' => str_replace($find, $replace, $customMessage),
			'mail' => $row['email_address'],
			'subject' => str_replace($find, $replace, $customSubject),
		);
	}

	// Do we find someone?
	if (!empty($messages))
	{
		// Gotta use a function in a far far away file...
		require_once($sourcedir . '/Subs-Post.php');

		// Send the mail away!
		foreach($messages as $m)
			sendmail($m['mail'], $m['subject'], $m['message'], null, null, false);

		// OK, next thing, mark those users. Set inactive_mail to the date the user was added to the mail queue. Set to_delete as 1
		$smcFunc['db_query']('', '
			UPDATE {db_prefix}members
			SET inactive_mail = {int:sinceMail}, to_delete = {int:to_delete}
			WHERE id_member IN ({array_int:id_members})',
			array(
				'sinceMail' => $today,
				'id_members' => array_keys($messages),
				'to_delete' => 1,
			)
		);
	}

	// Next step. Find out if any user marked for potential deletion or deletion has logged in since then and reset their status. Don't reset the untouchable status...
	$smcFunc['db_query']('', '
		UPDATE {db_prefix}members
		SET inactive_mail = {int:zero}, to_delete = {int:zero}
		WHERE last_login > {int:sinceMail}
			AND inactive_mail > {int:zero}
			AND inactive_mail <= {int:two}',
		array(
			'sinceMail' => (int) $today - $sinceMail,
			'zero' => 0,
			'two' => 2,
		)
	);

	// Last step. Find those user the admin has decided to delete and see if the deletion date has been met.
	$request = $smcFunc['db_query']('', '
			SELECT id_member
			FROM {db_prefix}members
			WHERE to_delete = {int:toDelete}
				AND inactive_mail < {int:today}',
			array(
				'toDelete' => 2,
				'today' => $today,
			)
		);

	$usersToDelete = array();

	while($row = $smcFunc['db_fetch_assoc']($request))
		$usersToDelete[] = $row['id_member'];

	// Any lucky ones?
	if (!empty($usersToDelete))
	{
		require_once($sourcedir . '/emailInactiveUsers.php');

		// This is a very expensive function :(
		eiu_deleteMembers($usersToDelete);

		// Re-build the "to delete" cache.
		cache_put_data('eiu_users-2', null, 3600);
	}

	// And... we're done!
	return true;
}
]]></add>
		</operation>
	</file>
</modification><commit_msg>Yet moar changes!<commit_after><?xml version="1.0" ?>
<!DOCTYPE modification SYSTEM "http://www.simplemachines.org/xml/modification">

<modification xmlns="http://www.simplemachines.org/xml/modification" xmlns:smf="http://www.simplemachines.org/">
	<id>Suki:eiu</id>
	<version>1.0</version>

	<file name="$sourcedir/ScheduledTasks.php">
		<operation>
			<search position="end" />
			<add><![CDATA[
/**
 * Send mails to inactive users, also delete them if they haven't logged in since then.
 *
 * Column to_delete hold the current state of the account:
 * 0 normal, up to date user
 * 1 mail has been sent, user starts her/his grace period after mail was sent.
 * 2 User has not been logged and her/his grace period is over, marked for admin deletion. These are the users who will appear on the mods user list.
 * 3 Admin has marked this user for deletion and will be deleted next time the scheduled task is executed.
 * 4 "Untouchable" means the user will not be fetched by the mod even if the account complies with all of the criteria to be marked for deletion.
 * Column inactive_mail holds a different unix timestamp depending on the account current state:
 * 0 if the user is up to date.
 * It will hold the date the mail was sent to the mail queue when the user to_delete column is set to 1. This time is then used to check if their grace period is over or for resetting their status.
 *
 * @return boolean true The code inside the scheduled task was executed.
 */
function scheduled_emailInactiveUsers()
{
	global $smcFunc, $modSettings, $txt, $sourcedir, $mbname;
	global $scripturl;

	// The mod must be enable
	if (empty($modSettings['eiu_enable']))
		return true;

	loadLanguage('emailInactiveUsers');

	// Today is a good day to do stuff don't you think?
	$today = time();

	// Is there any custom message?
	$customMessage = !empty($modSettings['eiu_message']) ? $modSettings['eiu_message'] : $txt['eiu_custom_message'];
	$customSubject = !empty($modSettings['eiu_subject']) ? $modSettings['eiu_subject'] : $txt['eiu_custom_subject'];
	$postLimit = !empty($modSettings['eiu_posts']) ? $modSettings['eiu_posts'] : 5;

	// How many days must the user needs to be inactive to get the mail? lets stay safe here and declare a default value too.
	$inactiveFor = 86400 * (!empty($modSettings['eiu_inactiveFor']) ? $modSettings['eiu_inactiveFor'] : 15);

	// The user hasn't been logged in since the mail was sent huh? how many days are we gonna wait until the account gets marked for deletion?
	$sinceMail = 86400 * (!empty($modSettings['eiu_sinceMail']) ? $modSettings['eiu_sinceMail'] : 15);

	// The groups from which the users will be fetched from.
	$inGroups = !empty($modSettings['eiu_groups']) ? unserialize($modSettings['eiu_groups']) : array();

	// Don't count the main admin group, AKA id_group 1
	if (!empty($inGroups))
		$inGroups = array_diff($inGroups, array(1));

	// We gotta do a nasty thing here, we have to format a "FIND_IN_SET" for each selected group. Thanks to this we need PHP 5.3 or grater...
	if (!empty($inGroups))
		$additionalgroups = array_map(
			function($k) {
				return ' OR FIND_IN_SET('. $k .', additional_groups)';
			}, $inGroups);

	// For those who still want to use this but don't have php 5.3
	/* if (!empty($inGroups))
		foreach ($inGroups as $k)
			$additionalgroups[] = ' OR FIND_IN_SET('. $k .', additional_groups)'; */

	else
		$additionalgroups = false;

	// Right, we got all we need, lets do some expensive queries.
	$request = $smcFunc['db_query']('', '
			SELECT id_member, email_address, inactive_mail, member_name, real_name, last_login
			FROM {db_prefix}members
			WHERE inactive_mail = 0
				AND posts <= {int:postLimit}
				AND last_login < {int:inactiveFor}
				AND date_registered < {int:inactiveFor}
				AND is_activated = 1
				AND to_delete = 0
				AND email_address is NOT NULL
				AND (id_group IN ({array_int:groups})
					OR id_post_group IN ({array_int:groups})
					'. (!empty($additionalgroups) ? implode(' ', $additionalgroups) : ''). ')',
			array(
				'inactiveFor' => $today - $inactiveFor,
				'groups' => $inGroups,
				'postLimit' => $postLimit,
			)
		);

	$messages = array();

	while($row = $smcFunc['db_fetch_assoc']($request))
	{
		// Lets create the message. Replace our wildcards with the actual data.
		$replacements = array(
			'{user_name}' => $row['real_name'],
			'{display_name}' => $row['member_name'],
			'{last_login}' => timeformat($row['last_login']),
			'{forum_name}' => $mbname,
			'{forum_url}' => $scripturl,
		);

		// Split the replacements up into two arrays, for use with str_replace.
		$find = array();
		$replace = array();

		foreach ($replacements as $f => $r)
		{
			$find[] = $f;
			$replace[] = $r;
		}

		$messages[$row['id_member']] = array(
			'message' => str_replace($find, $replace, $customMessage),
			'mail' => $row['email_address'],
			'subject' => str_replace($find, $replace, $customSubject),
		);
	}

	// Do we find someone?
	if (!empty($messages))
	{
		// Gotta use a function in a far far away file...
		require_once($sourcedir . '/Subs-Post.php');

		// Send the mail away!
		foreach($messages as $m)
			sendmail($m['mail'], $m['subject'], $m['message'], null, null, false);

		// OK, next thing, mark those users. Set inactive_mail to the date the user was added to the mail queue. Set to_delete as 1
		$smcFunc['db_query']('', '
			UPDATE {db_prefix}members
			SET inactive_mail = {int:sinceMail}, to_delete = {int:to_delete}
			WHERE id_member IN ({array_int:id_members})',
			array(
				'sinceMail' => $today,
				'id_members' => array_keys($messages),
				'to_delete' => 1,
			)
		);
	}

	// Next step. Find out if any user marked for potential deletion or deletion has logged in since then and reset their status. Don't reset the untouchable status...
	$smcFunc['db_query']('', '
		UPDATE {db_prefix}members
		SET inactive_mail = {int:zero}, to_delete = {int:zero}
		WHERE inactive_mail > {int:zero}
			AND last_login > inactive_mail
			AND to_delete >= {int:cero}
			AND to_delete <= {int:tres}',
		array(
			'cero' => 0,
			'tres' => 3,
		)
	);

	/* Next. Find all users whose email was sent and see if their grace period time has expired, if so, mark them for deletion.
	 * Include the group check since its possible the users has changed their group since then.
	 * It is also possible for an user to log in at the very last minute that is, after the admin set the account for deletion but before the next scheduled task is executed... lucky bastard! */
	$request = $smcFunc['db_query']('', '
		UPDATE {db_prefix}members
		SET to_delete = {int:dos}
		WHERE inactive_mail > {int:cero}
			AND last_login < inactive_mail + {int:sinceMail}
			AND posts <= {int:postLimit}
			AND date_registered < inactive_mail + {int:sinceMail}
			AND is_activated = {int:uno}
			AND to_delete = {int:uno}
			AND (id_group IN ({array_int:groups})
				OR id_post_group IN ({array_int:groups})
				'. (!empty($additionalgroups) ? implode(' ', $additionalgroups) : ''). ')',
		array(
			'groups' => $inGroups,
			'postLimit' => $postLimit,
			'cero' => 0,
			'uno' => 1,
			'dos' => 2,
			'sinceMail' => $sinceMail,
		)
	);

	// Last step. Find those user the admin has decided to delete. No further checks here, it is all based on having "to_delete" set to 3.
	$request = $smcFunc['db_query']('', '
			SELECT id_member
			FROM {db_prefix}members
			WHERE to_delete = {int:toDelete}',
			array(
				'toDelete' => 3,
			)
		);

	$usersToDelete = array();

	while($row = $smcFunc['db_fetch_assoc']($request))
		$usersToDelete[] = $row['id_member'];

	// Any lucky ones?
	if (!empty($usersToDelete))
	{
		// Redundant but still need to be sure.
		require_once($sourcedir . '/emailInactiveUsers.php');

		// This is a very expensive function :(
		eiu_deleteMembers($usersToDelete);

		// Re-build the "to delete" cache.
		cache_put_data('eiu_users-2', null, 3600);
	}

	// And... we're done!
	return true;
}
]]></add>
		</operation>
	</file>
</modification>
{'fraction_non_alphanumeric': 0.13892484840226205, 'fraction_numerical': 0.006268310962730803, 'mean_word_length': 3.9891230455472466, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 2, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 10}, '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': '1800802', 'n_tokens_mistral': 5334, 'n_tokens_neox': 4719, 'n_words': 1583}