<commit_before><?
/**
 * Ngroup (nested group)
 *
 * @property $depth
 * @author <NAME> <<EMAIL>>
 * @package Basisentscheid
 */


class Ngroup extends Relation {

	public $parent;
	public $name;
	public $active;
	public $minimum_population;

	protected $boolean_fields = array("active");


	/**
	 * get the current Ngroup object from GET or redirect to the default Ngroup
	 *
	 * $_SESSION['ngroup'] must be used for navigation only, not for actual content or action!
	 *
	 * @return object
	 */
	public static function get() {

		if (!empty($_GET['ngroup'])) {
			$ngroup = new Ngroup($_GET['ngroup']);
			if ($ngroup->active) {
				// override differing GET parameter
				$_SESSION['ngroup'] = $ngroup->id;
				return $ngroup;
			}
		}

		// redirect to ngroup from session
		if (!empty($_SESSION['ngroup'])) {
			$ngroup = new Ngroup($_SESSION['ngroup']);
			if ($ngroup->active) {
				redirect(BN."?ngroup=".$ngroup->id);
			}
		}

		// redirect to default ngroup
		$default_ngroup = DB::fetchfield("SELECT id FROM ngroups WHERE active=TRUE ORDER BY id LIMIT 1");
		if (!$default_ngroup) error(_("No active groups found"));
		redirect(BN."?ngroup=".$default_ngroup);
	}


	/**
	 * sort parents before children
	 *
	 * The output array uses the Ngroup IDs as indexes, so the indexes are independent from the order.
	 *
	 * @param array   $ngroups input
	 * @param integer $parent  (optional) starting parent ID
	 * @param integer $depth   (optional) internal
	 * @return array           output
	 */
	public static function parent_sort(array $ngroups, $parent=0, $depth=0) {
		$result = array();
		foreach ($ngroups as $key => $ngroup) {
			if ($ngroup->parent == $parent) {
				$ngroup->depth = $depth;
				unset($ngroups[$key]);
				$result[$ngroup->id] = $ngroup;
				$result += self::parent_sort($ngroups, $ngroup->id, $depth + 1);
			}
		}
		return $result;
	}


	/**
	 * sort parents before children, return only active ngroups
	 *
	 * This is a separate function, because it is used by the navigation and thus probably performance critical.
	 *
	 * The output array uses the Ngroup IDs as indexes, so the indexes are independent from the order.
	 *
	 * @param array   $ngroups input
	 * @param integer $parent  (optional) starting parent ID
	 * @return array           output
	 */
	public static function parent_sort_active(array $ngroups, $parent=0) {
		$result = array();
		foreach ($ngroups as $key => $ngroup) {
			if ($ngroup->parent == $parent) {
				unset($ngroups[$key]);
				if ($ngroup->active) $result[$ngroup->id] = $ngroup;
				$result += self::parent_sort_active($ngroups, $ngroup->id);
			}
		}
		return $result;
	}


	/**
	 * sort parents before children, return only active ngroups and ngroups with active children
	 *
	 * This is a separate function, because it is used by the start page and thus probably performance critical.
	 *
	 * The output array uses the Ngroup IDs as indexes, so the indexes are independent from the order.
	 *
	 * @param array   $ngroups input
	 * @param integer $parent  (optional) starting parent ID
	 * @param integer $depth   (optional) internal
	 * @return array           output: sorted array and boolean if any ngroups is active
	 */
	public static function parent_sort_active_tree(array $ngroups, $parent=0, $depth=0) {
		$result = array();
		$active = false;
		foreach ($ngroups as $key => $ngroup) {
			if ($ngroup->parent == $parent) {
				$ngroup->depth = $depth;
				unset($ngroups[$key]);
				list($result_children, $active_children) = self::parent_sort_active_tree($ngroups, $ngroup->id, $depth + 1);
				// show only if active or with active children
				if ($ngroup->active or $active_children) {
					$result[$ngroup->id] = $ngroup;
					$result += $result_children;
					$active = true;
				}
			}
		}
		return array($result, $active);
	}


	/**
	 * options for drop down menu
	 *
	 * Here we use all ngroups, not only the active ones.
	 *
	 * @param integer $parent
	 * @return array
	 */
	public static function options($parent) {
		$options = array();
		$sql = "SELECT ngroups.*, member FROM ngroups
			LEFT JOIN members_ngroups ON members_ngroups.ngroup = ngroups.id AND members_ngroups.member = ".intval(Login::$member->id)."
			ORDER BY name";
		$result = DB::query($sql);
		$ngroups = array();
		while ( $ngroup = DB::fetch_object($result, "Ngroup") ) $ngroups[] = $ngroup;
		$ngroups = Ngroup::parent_sort($ngroups, $parent);
		// entitled ngroups
		foreach ($ngroups as $ngroup) {
			if (!$ngroup->member) continue;
			$options[$ngroup->id] = $ngroup->name." ("._("entitled").")";
		}
		// not entitled ngroups
		foreach ($ngroups as $ngroup) {
			if ($ngroup->member) continue;
			$options[$ngroup->id] = $ngroup->name;
		}
		return $options;
	}


	/**
	 * number of proposals
	 *
	 * @return integer
	 */
	public function proposals_count() {
		$sql = "SELECT count(1) FROM proposals
			JOIN issues ON proposals.issue = issues.id
 			JOIN areas ON issues.area = areas.id
 			WHERE ngroup=".intval($this->id);
		return DB::fetchfield($sql);
	}


	/**
	 * number of voting periods
	 *
	 * @return integer
	 */
	public function periods_count() {
		$sql = "SELECT count(1) FROM periods
 			WHERE ngroup=".intval($this->id);
		return DB::fetchfield($sql);
	}


	/**
	 * number of issues the logged in member has not yet voted on
	 *
	 * @return integer
	 */
	public function not_yet_voted_issues_count() {
		$sql = "SELECT count(1) FROM vote_tokens
			JOIN issues ON issues.id = vote_tokens.issue AND issues.state = 'voting'
 			JOIN areas ON issues.area = areas.id AND areas.ngroup = ".intval($this->id)."
 			LEFT JOIN vote_votes USING (token)
			WHERE vote_tokens.member = ".intval(Login::$member->id)."
				AND vote_votes.vote IS NULL";
		return DB::fetchfield($sql);
	}


	/**
	 * message about not yet voted issues
	 *
	 * @param integer $count
	 * @return string<commit_msg>fix: Notice:  Trying to get property of non-object in /www/basisentscheid/inc/classes/Ngroup.php on line 201<commit_after><?
/**
 * Ngroup (nested group)
 *
 * @property $depth
 * @author <NAME> <<EMAIL>>
 * @package Basisentscheid
 */


class Ngroup extends Relation {

	public $parent;
	public $name;
	public $active;
	public $minimum_population;

	protected $boolean_fields = array("active");


	/**
	 * get the current Ngroup object from GET or redirect to the default Ngroup
	 *
	 * $_SESSION['ngroup'] must be used for navigation only, not for actual content or action!
	 *
	 * @return object
	 */
	public static function get() {

		if (!empty($_GET['ngroup'])) {
			$ngroup = new Ngroup($_GET['ngroup']);
			if ($ngroup->active) {
				// override differing GET parameter
				$_SESSION['ngroup'] = $ngroup->id;
				return $ngroup;
			}
		}

		// redirect to ngroup from session
		if (!empty($_SESSION['ngroup'])) {
			$ngroup = new Ngroup($_SESSION['ngroup']);
			if ($ngroup->active) {
				redirect(BN."?ngroup=".$ngroup->id);
			}
		}

		// redirect to default ngroup
		$default_ngroup = DB::fetchfield("SELECT id FROM ngroups WHERE active=TRUE ORDER BY id LIMIT 1");
		if (!$default_ngroup) error(_("No active groups found"));
		redirect(BN."?ngroup=".$default_ngroup);
	}


	/**
	 * sort parents before children
	 *
	 * The output array uses the Ngroup IDs as indexes, so the indexes are independent from the order.
	 *
	 * @param array   $ngroups input
	 * @param integer $parent  (optional) starting parent ID
	 * @param integer $depth   (optional) internal
	 * @return array           output
	 */
	public static function parent_sort(array $ngroups, $parent=0, $depth=0) {
		$result = array();
		foreach ($ngroups as $key => $ngroup) {
			if ($ngroup->parent == $parent) {
				$ngroup->depth = $depth;
				unset($ngroups[$key]);
				$result[$ngroup->id] = $ngroup;
				$result += self::parent_sort($ngroups, $ngroup->id, $depth + 1);
			}
		}
		return $result;
	}


	/**
	 * sort parents before children, return only active ngroups
	 *
	 * This is a separate function, because it is used by the navigation and thus probably performance critical.
	 *
	 * The output array uses the Ngroup IDs as indexes, so the indexes are independent from the order.
	 *
	 * @param array   $ngroups input
	 * @param integer $parent  (optional) starting parent ID
	 * @return array           output
	 */
	public static function parent_sort_active(array $ngroups, $parent=0) {
		$result = array();
		foreach ($ngroups as $key => $ngroup) {
			if ($ngroup->parent == $parent) {
				unset($ngroups[$key]);
				if ($ngroup->active) $result[$ngroup->id] = $ngroup;
				$result += self::parent_sort_active($ngroups, $ngroup->id);
			}
		}
		return $result;
	}


	/**
	 * sort parents before children, return only active ngroups and ngroups with active children
	 *
	 * This is a separate function, because it is used by the start page and thus probably performance critical.
	 *
	 * The output array uses the Ngroup IDs as indexes, so the indexes are independent from the order.
	 *
	 * @param array   $ngroups input
	 * @param integer $parent  (optional) starting parent ID
	 * @param integer $depth   (optional) internal
	 * @return array           output: sorted array and boolean if any ngroups is active
	 */
	public static function parent_sort_active_tree(array $ngroups, $parent=0, $depth=0) {
		$result = array();
		$active = false;
		foreach ($ngroups as $key => $ngroup) {
			if ($ngroup->parent == $parent) {
				$ngroup->depth = $depth;
				unset($ngroups[$key]);
				list($result_children, $active_children) = self::parent_sort_active_tree($ngroups, $ngroup->id, $depth + 1);
				// show only if active or with active children
				if ($ngroup->active or $active_children) {
					$result[$ngroup->id] = $ngroup;
					$result += $result_children;
					$active = true;
				}
			}
		}
		return array($result, $active);
	}


	/**
	 * options for drop down menu
	 *
	 * Here we use all ngroups, not only the active ones.
	 *
	 * @param integer $parent
	 * @return array
	 */
	public static function options($parent) {
		$options = array();
		$sql = "SELECT ngroups.*, member FROM ngroups
			LEFT JOIN members_ngroups ON members_ngroups.ngroup = ngroups.id AND members_ngroups.member = ".intval(Login::$member->id)."
			ORDER BY name";
		$result = DB::query($sql);
		$ngroups = array();
		while ( $ngroup = DB::fetch_object($result, "Ngroup") ) $ngroups[] = $ngroup;
		$ngroups = Ngroup::parent_sort($ngroups, $parent);
		// entitled ngroups
		foreach ($ngroups as $ngroup) {
			if (!$ngroup->member) continue;
			$options[$ngroup->id] = $ngroup->name." ("._("entitled").")";
		}
		// not entitled ngroups
		foreach ($ngroups as $ngroup) {
			if ($ngroup->member) continue;
			$options[$ngroup->id] = $ngroup->name;
		}
		return $options;
	}


	/**
	 * number of proposals
	 *
	 * @return integer
	 */
	public function proposals_count() {
		$sql = "SELECT count(1) FROM proposals
			JOIN issues ON proposals.issue = issues.id
 			JOIN areas ON issues.area = areas.id
 			WHERE ngroup=".intval($this->id);
		return DB::fetchfield($sql);
	}


	/**
	 * number of voting periods
	 *
	 * @return integer
	 */
	public function periods_count() {
		$sql = "SELECT count(1) FROM periods
 			WHERE ngroup=".intval($this->id);
		return DB::fetchfield($sql);
	}


	/**
	 * number of issues the logged in member has not yet voted on
	 *
	 * @return integer
	 */
	public function not_yet_voted_issues_count() {
		if (!Login::$member) return;
		$sql = "SELECT count(1) FROM vote_tokens
			JOIN issues ON issues.id = vote_tokens.issue AND issues.state = 'voting'
 			JOIN areas ON issues.area = areas.id AND areas.ngroup = ".intval($this->id)."
 			LEFT JOIN vote_votes USING (token)
			WHERE vote_tokens.member = ".intval(Login::$member->id)."
				AND vote_votes.vote IS NULL";
		return DB::fetchfield($sql);
	}


	/**
	 * message about not yet voted issues
	 *
	 * @param integer $count
	 * @return string
{'fraction_non_alphanumeric': 0.13914218169537318, 'fraction_numerical': 0.0021107733873691322, 'mean_word_length': 3.4463213213213213, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, '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': '7622093', 'n_tokens_mistral': 4187, 'n_tokens_neox': 3654, 'n_words': 1166}