+ }
+ $uf = new UserFilter($cond);
+ return $uf->getTotalCount();
+ }
+
+ /** Get the count of subscribers with non valid redirection.
+ */
+ public function lostSubscriberCount($sex = null)
+ {
+ return $this->subscriberCount(true, $sex);
+ }
+
+ /** Get the number of subscribers to the NL whose last received mailing was $last.
+ * @p $last ID of the issue for which subscribers should be counted.
+ * @return Number of subscribers
+ */
+ public function subscriberCountForLast($last)
+ {
+ return XDB::fetchOneCell('SELECT COUNT(uid)
+ FROM newsletter_ins
+ WHERE nlid = {?} AND last = {?}', $this->id, $last);
+ }
+
+ /** Retrieve the list of newsletters a user has subscribed to
+ * @p $user User whose subscriptions should be retrieved (if null, use session user).
+ * @return Array of newsletter IDs
+ */
+ public static function getUserSubscriptions($user = null)
+ {
+ if (is_null($user)) {
+ $user = S::user();
+ }
+ $res = XDB::query('SELECT nlid
+ FROM newsletter_ins
+ WHERE uid = {?}',
+ $user->id());
+ return $res->fetchColumn();
+ }
+
+ /** Retrieve the UserFilterBuilder for subscribers to this NL.
+ * This is the place where NL-specific filters may be allowed or prevented.
+ * @p $envprefix Prefix to use for env fields (cf. UserFilterBuilder)
+ * @return A UserFilterBuilder object using the given env prefix
+ */
+ public function getSubscribersUFB($envprefix = '')
+ {
+ require_once 'ufbuilder.inc.php';
+ return new UFB_NewsLetter($this->criteria, $envprefix);
+ }
+
+ // }}}
+ // {{{ Permissions related functions
+
+ /** For later use: check whether a given user may subscribe to this newsletter.
+ * @p $user User whose access should be checked
+ * @return Boolean: whether the user may subscribe to the NL.
+ */
+ public function maySubscribe($user = null)
+ {
+ return true;
+ }
+
+ /** Whether a given user may edit this newsletter
+ * @p $uid UID of the user whose perms should be checked (if null, use current user)
+ * @return Boolean: whether the user may edit the NL
+ */
+ public function mayEdit($user = null)
+ {
+ if (is_null($user)) {
+ $user = S::user();
+ }
+ if ($user->checkPerms('admin')) {
+ return true;
+ }
+ $res = XDB::query('SELECT perms
+ FROM group_members
+ WHERE asso_id = {?} AND uid = {?}',
+ $this->group_id, $user->id());
+ return ($res->numRows() && $res->fetchOneCell() == 'admin');
+ }
+
+ /** Whether a given user may submit articles to this newsletter using X.org validation system
+ * @p $user User whose access should be checked (if null, use current user)
+ * @return Boolean: whether the user may submit articles
+ */
+ public function maySubmit($user = null)
+ {
+ // Submission of new articles is only enabled for the X.org NL (and forbidden when viewing issues on X.net)
+ return ($this->group == self::GROUP_XORG && !isset($GLOBALS['IS_XNET_SITE']));
+ }
+
+ // }}}
+ // {{{ Display-related functions: cssFile, tplFile, prefix, admin_prefix, admin_links_enabled, automatic_mailings_enabled
+
+ /** Get the name of the css file used to display this newsletter.
+ */
+ public function cssFile()
+ {
+ if ($this->custom_css) {
+ $base = $this->group;
+ } else {
+ $base = self::FORMAT_DEFAULT_GROUP;
+ }
+ return 'nl.' . $base . '.css';
+ }
+
+ /** Get the name of the template file used to display this newsletter.
+ */
+ public function tplFile()
+ {
+ if ($this->custom_css) {
+ $base = $this->group;
+ } else {
+ $base = self::FORMAT_DEFAULT_GROUP;
+ }
+ return 'newsletter/nl.' . $base . '.mail.tpl';
+ }
+
+ /** Get the prefix leading to the page for this NL
+ * Only X.org / AX / X groups may be seen on X.org.
+ */
+ public function prefix($enforce_xnet=true, $with_group=true)
+ {
+ if (!empty($GLOBALS['IS_XNET_SITE'])) {
+ if ($with_group) {
+ return $this->group . '/nl';
+ } else {
+ return 'nl';
+ }
+ }
+ switch ($this->group) {
+ case self::GROUP_XORG:
+ return 'nl';
+ case self::GROUP_AX:
+ return 'ax';
+ case self::GROUP_EP:
+ return 'epletter';
+ case self::GROUP_FX:
+ return 'fxletter';
+ default:
+ // Don't display groups NLs on X.org
+ assert(!$enforce_xnet);
+ }
+ }
+
+ /** Get the prefix to use for all 'admin' pages of this NL.
+ */
+ public function adminPrefix($enforce_xnet=true, $with_group=true)
+ {
+ if (!empty($GLOBALS['IS_XNET_SITE'])) {
+ if ($with_group) {
+ return $this->group . '/admin/nl';
+ } else {
+ return 'admin/nl';
+ }
+ }
+ switch ($this->group) {
+ case self::GROUP_XORG:
+ return 'admin/newsletter';
+ case self::GROUP_AX:
+ return 'ax/admin';
+ case self::GROUP_EP:
+ return 'epletter/admin';
+ case self::GROUP_FX:
+ return 'fxletter/admin';
+ default:
+ // Don't display groups NLs on X.org
+ assert(!$enforce_xnet);
+ }
+ }
+
+ /** Get the prefix to use for all 'stat' pages of this NL.
+ */
+ public function statPrefix($enforce_xnet = true, $with_group = true)
+ {
+ if (!empty($GLOBALS['IS_XNET_SITE'])) {
+ if ($with_group) {
+ return $this->group . '/stat/nl';
+ } else {
+ return 'stat/nl';