[DATABASE] Set NULL in DB_DataObject in a more reliable manner

Also stop assuming that FeedSub::sub_state (enum) and FeedSub::sub_end
(datetime) can possibly be set to an empty string.
This commit is contained in:
Alexei Sorokin 2019-09-11 08:32:19 +03:00
parent 5b797328f2
commit 0a5a3845db
4 changed files with 324 additions and 285 deletions

View File

@ -1,48 +1,40 @@
<?php <?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social. If not, see <http://www.gnu.org/licenses/>.
/** /**
* StatusNet, the distributed open-source microblogging tool
*
* Settings for email * Settings for email
* *
* PHP version 5
*
* LICENCE: 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/>.
*
* @category Settings * @category Settings
* @package StatusNet * @package GNUsocial
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2008-2009 StatusNet, Inc. * @copyright 2008-2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
* @link http://status.net/
*/ */
if (!defined('GNUSOCIAL')) { exit(1); } defined('GNUSOCIAL') || die();
/** /**
* Settings for email * Settings for email
* *
* @category Settings * @copyright 2008-2009 StatusNet, Inc.
* @package StatusNet * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
* @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
* *
* @see Widget * @see Widget
*/ */
class EmailsettingsAction extends SettingsAction class EmailsettingsAction extends SettingsAction
{ {
/** /**
@ -50,7 +42,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() public function title()
{ {
// TRANS: Title for e-mail settings. // TRANS: Title for e-mail settings.
return _('Email settings'); return _('Email settings');
@ -61,7 +53,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() public function getInstructions()
{ {
// XXX: For consistency of parameters in messages, this should be a // XXX: For consistency of parameters in messages, this should be a
// regular parameters, replaced with sprintf(). // regular parameters, replaced with sprintf().
@ -70,7 +62,7 @@ class EmailsettingsAction extends SettingsAction
return _('Manage how you get email from %%site.name%%.'); return _('Manage how you get email from %%site.name%%.');
} }
function showScripts() public function showScripts()
{ {
parent::showScripts(); parent::showScripts();
$this->script('emailsettings.js'); $this->script('emailsettings.js');
@ -85,7 +77,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function showContent() public function showContent()
{ {
$user = $this->scoped->getUser(); $user = $this->scoped->getUser();
@ -106,50 +98,58 @@ class EmailsettingsAction extends SettingsAction
$this->element('p', array('class' => 'form_note'), _('Current confirmed email address.')); $this->element('p', array('class' => 'form_note'), _('Current confirmed email address.'));
$this->hidden('email', $user->email); $this->hidden('email', $user->email);
// TRANS: Button label to remove a confirmed e-mail address. // TRANS: Button label to remove a confirmed e-mail address.
$this->submit('remove', _m('BUTTON','Remove')); $this->submit('remove', _m('BUTTON', 'Remove'));
} else { } else {
try { try {
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
$this->element('p', array('id' => 'form_unconfirmed'), $confirm->address); $this->element('p', array('id' => 'form_unconfirmed'), $confirm->address);
$this->element('p', array('class' => 'form_note'), $this->element(
// TRANS: Form note in e-mail settings form. 'p',
_('Awaiting confirmation on this address. '. ['class' => 'form_note'],
'Check your inbox (and spam box!) for a message '. // TRANS: Form note in e-mail settings form.
'with further instructions.')); _('Awaiting confirmation on this address. '.
'Check your inbox (and spam box!) for a message '.
'with further instructions.')
);
$this->hidden('email', $confirm->address); $this->hidden('email', $confirm->address);
// TRANS: Button label to cancel an e-mail address confirmation procedure. // TRANS: Button label to cancel an e-mail address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel')); $this->submit('cancel', _m('BUTTON', 'Cancel'));
} catch (NoResultException $e) { } catch (NoResultException $e) {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for e-mail address input in e-mail settings form. // TRANS: Field label for e-mail address input in e-mail settings form.
$this->input('email', _('Email address'), $this->input(
$this->trimmed('email') ?: null, 'email',
// TRANS: Instructions for e-mail address input form. Do not translate _('Email address'),
// TRANS: "example.org". It is one of the domain names reserved for $this->trimmed('email') ?: null,
// TRANS: use in examples by http://www.rfc-editor.org/rfc/rfc2606.txt. // TRANS: Instructions for e-mail address input form. Do not translate
// TRANS: Any other domain may be owned by a legitimate person or // TRANS: "example.org". It is one of the domain names reserved for
// TRANS: organization. // TRANS: use in examples by http://www.rfc-editor.org/rfc/rfc2606.txt.
_('Email address, like "UserName@example.org"')); // TRANS: Any other domain may be owned by a legitimate person or
// TRANS: organization.
_('Email address, like "UserName@example.org"')
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label for adding an e-mail address in e-mail settings form. // TRANS: Button label for adding an e-mail address in e-mail settings form.
$this->submit('add', _m('BUTTON','Add')); $this->submit('add', _m('BUTTON', 'Add'));
} }
} }
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
if (common_config('emailpost', 'enabled') && $user->email) { if (common_config('emailpost', 'enabled') && $user->email) {
$this->elementStart('fieldset', array('id' => 'settings_email_incoming')); $this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
// TRANS: Form legend for incoming e-mail settings form. // TRANS: Form legend for incoming e-mail settings form.
$this->element('legend', null, _('Incoming email')); $this->element('legend', null, _('Incoming email'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailpost', $this->checkbox(
// TRANS: Checkbox label in e-mail preferences form. 'emailpost',
_('I want to post notices by email.'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailpost); _('I want to post notices by email.'),
$user->emailpost
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
@ -168,12 +168,15 @@ class EmailsettingsAction extends SettingsAction
$this->element('span', 'address', $user->incomingemail); $this->element('span', 'address', $user->incomingemail);
// @todo XXX: Looks a little awkward in the UI. // @todo XXX: Looks a little awkward in the UI.
// Something like "xxxx@identi.ca Send email ..". Needs improvement. // Something like "xxxx@identi.ca Send email ..". Needs improvement.
$this->element('span', 'input_instructions', $this->element(
// TRANS: Form instructions for incoming e-mail form in e-mail settings. 'span',
_('Send email to this address to post new notices.')); 'input_instructions',
// TRANS: Form instructions for incoming e-mail form in e-mail settings.
_('Send email to this address to post new notices.')
);
$this->elementEnd('p'); $this->elementEnd('p');
// TRANS: Button label for removing a set sender e-mail address to post notices from. // TRANS: Button label for removing a set sender e-mail address to post notices from.
$this->submit('removeincoming', _m('BUTTON','Remove')); $this->submit('removeincoming', _m('BUTTON', 'Remove'));
} }
$this->elementStart('p'); $this->elementStart('p');
@ -189,7 +192,7 @@ class EmailsettingsAction extends SettingsAction
$this->elementEnd('p'); $this->elementEnd('p');
// TRANS: Button label for adding an e-mail address to send notices from. // TRANS: Button label for adding an e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New')); $this->submit('newincoming', _m('BUTTON', 'New'));
$this->elementEnd('div'); // div#emailincoming $this->elementEnd('div'); // div#emailincoming
@ -204,34 +207,42 @@ class EmailsettingsAction extends SettingsAction
if (Event::handle('StartEmailFormData', array($this, $this->scoped))) { if (Event::handle('StartEmailFormData', array($this, $this->scoped))) {
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifysub', $this->checkbox(
// TRANS: Checkbox label in e-mail preferences form. 'emailnotifysub',
_('Send me notices of new subscriptions through email.'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailnotifysub); _('Send me notices of new subscriptions through email.'),
$user->emailnotifysub
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifymsg', $this->checkbox(
// TRANS: Checkbox label in e-mail preferences form. 'emailnotifymsg',
_('Send me email when someone sends me a private message.'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailnotifymsg); _('Send me email when someone sends me a private message.'),
$user->emailnotifymsg
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifyattn', $this->checkbox(
// TRANS: Checkbox label in e-mail preferences form. 'emailnotifyattn',
_('Send me email when someone sends me an "@-reply".'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailnotifyattn); _('Send me email when someone sends me an "@-reply".'),
$user->emailnotifyattn
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifynudge', $this->checkbox(
// TRANS: Checkbox label in e-mail preferences form. 'emailnotifynudge',
_('Allow friends to nudge me and send me an email.'), // TRANS: Checkbox label in e-mail preferences form.
$user->emailnotifynudge); _('Allow friends to nudge me and send me an email.'),
$user->emailnotifynudge
);
$this->elementEnd('li'); $this->elementEnd('li');
Event::handle('EndEmailFormData', array($this, $this->scoped)); Event::handle('EndEmailFormData', array($this, $this->scoped));
} }
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label to save e-mail preferences. // TRANS: Button label to save e-mail preferences.
$this->submit('save', _m('BUTTON','Save')); $this->submit('save', _m('BUTTON', 'Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
@ -242,7 +253,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return Confirm_address Email address confirmation for user, or null * @return Confirm_address Email address confirmation for user, or null
*/ */
function getConfirmation() public function getConfirmation()
{ {
$confirm = new Confirm_address(); $confirm = new Confirm_address();
@ -260,15 +271,15 @@ class EmailsettingsAction extends SettingsAction
{ {
if ($this->arg('save')) { if ($this->arg('save')) {
return $this->savePreferences(); return $this->savePreferences();
} else if ($this->arg('add')) { } elseif ($this->arg('add')) {
return $this->addAddress(); return $this->addAddress();
} else if ($this->arg('cancel')) { } elseif ($this->arg('cancel')) {
return $this->cancelConfirmation(); return $this->cancelConfirmation();
} else if ($this->arg('remove')) { } elseif ($this->arg('remove')) {
return $this->removeAddress(); return $this->removeAddress();
} else if ($this->arg('removeincoming')) { } elseif ($this->arg('removeincoming')) {
return $this->removeIncoming(); return $this->removeIncoming();
} else if ($this->arg('newincoming')) { } elseif ($this->arg('newincoming')) {
return $this->newIncoming(); return $this->newIncoming();
} }
@ -281,7 +292,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function savePreferences() public function savePreferences()
{ {
if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) { if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) {
$emailnotifysub = $this->booleanintstring('emailnotifysub'); $emailnotifysub = $this->booleanintstring('emailnotifysub');
@ -322,7 +333,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function addAddress() public function addAddress()
{ {
$user = $this->scoped->getUser(); $user = $this->scoped->getUser();
@ -344,16 +355,15 @@ class EmailsettingsAction extends SettingsAction
if (!Validate::email($email, common_config('email', 'check_domain'))) { if (!Validate::email($email, common_config('email', 'check_domain'))) {
// TRANS: Message given saving e-mail address that not valid. // TRANS: Message given saving e-mail address that not valid.
throw new ClientException(_('Not a valid email address.')); throw new ClientException(_('Not a valid email address.'));
} else if ($user->email == $email) { } elseif ($user->email === $email) {
// TRANS: Message given saving e-mail address that is already set. // TRANS: Message given saving e-mail address that is already set.
throw new ClientException(_('That is already your email address.')); throw new ClientException(_('That is already your email address.'));
} else if ($this->emailExists($email)) { } elseif ($this->emailExists($email)) {
// TRANS: Message given saving e-mail address that is already set for another user. // TRANS: Message given saving e-mail address that is already set for another user.
throw new ClientException(_('That email address already belongs to another user.')); throw new ClientException(_('That email address already belongs to another user.'));
} }
if (Event::handle('StartAddEmailAddress', array($user, $email))) { if (Event::handle('StartAddEmailAddress', array($user, $email))) {
$confirm = new Confirm_address(); $confirm = new Confirm_address();
$confirm->address = $email; $confirm->address = $email;
@ -385,7 +395,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function cancelConfirmation() public function cancelConfirmation()
{ {
$email = $this->trimmed('email'); $email = $this->trimmed('email');
@ -411,7 +421,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function removeAddress() public function removeAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -425,7 +435,7 @@ class EmailsettingsAction extends SettingsAction
} }
$original = clone($user); $original = clone($user);
$user->email = null; $user->email = DB_DataObject_Cast::sql('NULL');
// Throws exception on failure. Also performs it within a transaction. // Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($original); $user->updateWithKeys($original);
@ -438,7 +448,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function removeIncoming() public function removeIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
@ -448,7 +458,7 @@ class EmailsettingsAction extends SettingsAction
} }
$orig = clone($user); $orig = clone($user);
$user->incomingemail = null; $user->incomingemail = DB_DataObject_Cast::sql('NULL');
$user->emailpost = 0; $user->emailpost = 0;
// Throws exception on failure. Also performs it within a transaction. // Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig); $user->updateWithKeys($orig);
@ -462,7 +472,7 @@ class EmailsettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function newIncoming() public function newIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
$orig = clone($user); $orig = clone($user);
@ -485,7 +495,7 @@ class EmailsettingsAction extends SettingsAction
* @return boolean Whether the email already exists. * @return boolean Whether the email already exists.
*/ */
function emailExists($email) public function emailExists($email)
{ {
$user = common_current_user(); $user = common_current_user();

View File

@ -1,46 +1,39 @@
<?php <?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social. If not, see <http://www.gnu.org/licenses/>.
/** /**
* StatusNet, the distributed open-source microblogging tool * Settings for SMS.
* *
* Settings for SMS * @category Setting
* * @package GNUsocial
* PHP version 5
*
* LICENCE: 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/>.
*
* @category Settings
* @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @copyright 2008-2009 StatusNet, Inc. * @copyright 2008-2009 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
* @link http://status.net/
*/ */
if (!defined('GNUSOCIAL')) { exit(1); } defined('GNUSOCIAL') || die();
/** /**
* Settings for SMS * Settings for SMS
* *
* @category Settings * @copyright 2008-2009 StatusNet, Inc.
* @package StatusNet * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
* *
* @see SettingsAction * @see SettingsAction
*/ */
class SmssettingsAction extends SettingsAction class SmssettingsAction extends SettingsAction
{ {
protected function doPreparation() protected function doPreparation()
@ -56,7 +49,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return string Title of the page * @return string Title of the page
*/ */
function title() public function title()
{ {
// TRANS: Title for SMS settings. // TRANS: Title for SMS settings.
return _('SMS settings'); return _('SMS settings');
@ -67,7 +60,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return instructions for use * @return instructions for use
*/ */
function getInstructions() public function getInstructions()
{ {
// XXX: For consistency of parameters in messages, this should be a // XXX: For consistency of parameters in messages, this should be a
// regular parameters, replaced with sprintf(). // regular parameters, replaced with sprintf().
@ -76,7 +69,7 @@ class SmssettingsAction extends SettingsAction
return _('You can receive SMS messages through email from %%site.name%%.'); return _('You can receive SMS messages through email from %%site.name%%.');
} }
function showScripts() public function showScripts()
{ {
parent::showScripts(); parent::showScripts();
$this->autofocus('sms'); $this->autofocus('sms');
@ -90,7 +83,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function showContent() public function showContent()
{ {
$user = $this->scoped->getUser(); $user = $this->scoped->getUser();
@ -107,80 +100,105 @@ class SmssettingsAction extends SettingsAction
if ($user->sms) { if ($user->sms) {
$carrier = $user->getCarrier(); $carrier = $user->getCarrier();
$this->element('p', 'form_confirmed', $this->element(
$user->sms . ' (' . $carrier->name . ')'); 'p',
$this->element('p', 'form_guide', 'form_confirmed',
// TRANS: Form guide in SMS settings form. $user->sms . ' (' . $carrier->name . ')'
_('Current confirmed SMS-enabled phone number.')); );
$this->element(
'p',
'form_guide',
// TRANS: Form guide in SMS settings form.
_('Current confirmed SMS-enabled phone number.')
);
$this->hidden('sms', $user->sms); $this->hidden('sms', $user->sms);
$this->hidden('carrier', $user->carrier); $this->hidden('carrier', $user->carrier);
// TRANS: Button label to remove a confirmed SMS address. // TRANS: Button label to remove a confirmed SMS address.
$this->submit('remove', _m('BUTTON','Remove')); $this->submit('remove', _m('BUTTON', 'Remove'));
} else { } else {
try { try {
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
$carrier = Sms_carrier::getKV($confirm->address_extra); $carrier = Sms_carrier::getKV($confirm->address_extra);
$this->element('p', 'form_unconfirmed', $this->element(
$confirm->address . ' (' . $carrier->name . ')'); 'p',
$this->element('p', 'form_guide', 'form_unconfirmed',
// TRANS: Form guide in IM settings form. $confirm->address . ' (' . $carrier->name . ')'
_('Awaiting confirmation on this phone number.')); );
$this->element(
'p',
'form_guide',
// TRANS: Form guide in IM settings form.
_('Awaiting confirmation on this phone number.')
);
$this->hidden('sms', $confirm->address); $this->hidden('sms', $confirm->address);
$this->hidden('carrier', $confirm->address_extra); $this->hidden('carrier', $confirm->address_extra);
// TRANS: Button label to cancel a SMS address confirmation procedure. // TRANS: Button label to cancel a SMS address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel')); $this->submit('cancel', _m('BUTTON', 'Cancel'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for SMS address input in SMS settings form. // TRANS: Field label for SMS address input in SMS settings form.
$this->input('code', _('Confirmation code'), null, $this->input(
// TRANS: Form field instructions in SMS settings form. 'code',
_('Enter the code you received on your phone.')); _('Confirmation code'),
null,
// TRANS: Form field instructions in SMS settings form.
_('Enter the code you received on your phone.')
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label to confirm SMS confirmation code in SMS settings. // TRANS: Button label to confirm SMS confirmation code in SMS settings.
$this->submit('confirm', _m('BUTTON','Confirm')); $this->submit('confirm', _m('BUTTON', 'Confirm'));
} catch (NoResultException $e) { } catch (NoResultException $e) {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for SMS phone number input in SMS settings form. // TRANS: Field label for SMS phone number input in SMS settings form.
$this->input('sms', _('SMS phone number'), $this->input(
($this->arg('sms')) ? $this->arg('sms') : null, 'sms',
// TRANS: SMS phone number input field instructions in SMS settings form. _('SMS phone number'),
_('Phone number, no punctuation or spaces, '. ($this->arg('sms') ?: null),
'with area code.')); // TRANS: SMS phone number input field instructions in SMS settings form.
_('Phone number, no punctuation or spaces, ' .
'with area code.')
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->carrierSelect(); $this->carrierSelect();
// TRANS: Button label for adding a SMS phone number in SMS settings form. // TRANS: Button label for adding a SMS phone number in SMS settings form.
$this->submit('add', _m('BUTTON','Add')); $this->submit('add', _m('BUTTON', 'Add'));
} }
} }
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
if ($user->sms) { if ($user->sms) {
$this->elementStart('fieldset', array('id' => 'settings_sms_incoming_email')); $this->elementStart('fieldset', ['id' => 'settings_sms_incoming_email']);
// XXX: Confused! This is about SMS. Should this message be updated? // XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form legend for incoming SMS settings form. // TRANS: Form legend for incoming SMS settings form.
$this->element('legend', null, _('Incoming email')); $this->element('legend', null, _('Incoming email'));
if ($user->incomingemail) { if ($user->incomingemail) {
$this->element('p', 'form_unconfirmed', $user->incomingemail); $this->element('p', 'form_unconfirmed', $user->incomingemail);
$this->element('p', 'form_note', $this->element(
// XXX: Confused! This is about SMS. Should this message be updated? 'p',
// TRANS: Form instructions for incoming SMS e-mail address form in SMS settings. 'form_note',
_('Send email to this address to post new notices.')); // XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form instructions for incoming SMS e-mail address form in SMS settings.
_('Send email to this address to post new notices.')
);
// TRANS: Button label for removing a set sender SMS e-mail address to post notices from. // TRANS: Button label for removing a set sender SMS e-mail address to post notices from.
$this->submit('removeincoming', _m('BUTTON','Remove')); $this->submit('removeincoming', _m('BUTTON', 'Remove'));
} }
$this->element('p', 'form_guide', $this->element(
// XXX: Confused! This is about SMS. Should this message be updated? 'p',
// TRANS: Instructions for incoming SMS e-mail address input form. 'form_guide',
_('Make a new email address for posting to; '. // XXX: Confused! This is about SMS. Should this message be updated?
'cancels the old one.')); // TRANS: Instructions for incoming SMS e-mail address input form.
_('Make a new email address for posting to; ' .
'cancels the old one.')
);
// TRANS: Button label for adding an SMS e-mail address to send notices from. // TRANS: Button label for adding an SMS e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New')); $this->submit('newincoming', _m('BUTTON', 'New'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
} }
@ -190,17 +208,19 @@ class SmssettingsAction extends SettingsAction
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('smsnotify', $this->checkbox(
// TRANS: Checkbox label in SMS preferences form. 'smsnotify',
_('Send me notices through SMS; '. // TRANS: Checkbox label in SMS preferences form.
'I understand I may incur '. _('Send me notices through SMS; ' .
'exorbitant charges from my carrier.'), 'I understand I may incur ' .
$user->smsnotify); 'exorbitant charges from my carrier.'),
$user->smsnotify
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
// TRANS: Button label to save SMS preferences. // TRANS: Button label to save SMS preferences.
$this->submit('save', _m('BUTTON','Save')); $this->submit('save', _m('BUTTON', 'Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
@ -213,7 +233,7 @@ class SmssettingsAction extends SettingsAction
* *
* @todo very similar to EmailsettingsAction::getConfirmation(); refactor? * @todo very similar to EmailsettingsAction::getConfirmation(); refactor?
*/ */
function getConfirmation() public function getConfirmation()
{ {
$confirm = new Confirm_address(); $confirm = new Confirm_address();
@ -229,20 +249,19 @@ class SmssettingsAction extends SettingsAction
protected function doPost() protected function doPost()
{ {
if ($this->arg('save')) { if ($this->arg('save')) {
return $this->savePreferences(); return $this->savePreferences();
} else if ($this->arg('add')) { } elseif ($this->arg('add')) {
return $this->addAddress(); return $this->addAddress();
} else if ($this->arg('cancel')) { } elseif ($this->arg('cancel')) {
return $this->cancelConfirmation(); return $this->cancelConfirmation();
} else if ($this->arg('remove')) { } elseif ($this->arg('remove')) {
return $this->removeAddress(); return $this->removeAddress();
} else if ($this->arg('removeincoming')) { } elseif ($this->arg('removeincoming')) {
return $this->removeIncoming(); return $this->removeIncoming();
} else if ($this->arg('newincoming')) { } elseif ($this->arg('newincoming')) {
return $this->newIncoming(); return $this->newIncoming();
} else if ($this->arg('confirm')) { } elseif ($this->arg('confirm')) {
return $this->confirmCode(); return $this->confirmCode();
} }
// TRANS: Message given submitting a form with an unknown action in SMS settings. // TRANS: Message given submitting a form with an unknown action in SMS settings.
@ -256,7 +275,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function savePreferences() public function savePreferences()
{ {
$user = $this->scoped->getUser(); $user = $this->scoped->getUser();
@ -288,7 +307,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function addAddress() public function addAddress()
{ {
$user = common_current_user(); $user = common_current_user();
@ -312,7 +331,7 @@ class SmssettingsAction extends SettingsAction
if ($user->sms === $sms) { if ($user->sms === $sms) {
// TRANS: Message given saving SMS phone number that is already set. // TRANS: Message given saving SMS phone number that is already set.
throw new AlreadyFulfilledException(_('That is already your phone number.')); throw new AlreadyFulfilledException(_('That is already your phone number.'));
} else if ($this->smsExists($sms)) { } elseif ($this->smsExists($sms)) {
// TRANS: Message given saving SMS phone number that is already set for another user. // TRANS: Message given saving SMS phone number that is already set for another user.
throw new ClientException(_('That phone number already belongs to another user.')); throw new ClientException(_('That phone number already belongs to another user.'));
} }
@ -335,9 +354,11 @@ class SmssettingsAction extends SettingsAction
$carrier = Sms_carrier::getKV($carrier_id); $carrier = Sms_carrier::getKV($carrier_id);
mail_confirm_sms($confirm->code, mail_confirm_sms(
$user->nickname, $confirm->code,
$carrier->toEmailAddress($sms)); $user->nickname,
$carrier->toEmailAddress($sms)
);
// TRANS: Message given saving valid SMS phone number that is to be confirmed. // TRANS: Message given saving valid SMS phone number that is to be confirmed.
return _('A confirmation code was sent to the phone number you added. '. return _('A confirmation code was sent to the phone number you added. '.
@ -352,7 +373,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function cancelConfirmation() public function cancelConfirmation()
{ {
$sms = $this->trimmed('sms'); $sms = $this->trimmed('sms');
$carrier = $this->trimmed('carrier'); $carrier = $this->trimmed('carrier');
@ -379,7 +400,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function removeAddress() public function removeAddress()
{ {
$user = $this->scoped->getUser(); $user = $this->scoped->getUser();
@ -396,9 +417,9 @@ class SmssettingsAction extends SettingsAction
$original = clone($user); $original = clone($user);
$user->sms = null; $user->sms = DB_DataObject_Cast::sql('NULL');
$user->carrier = null; $user->carrier = DB_DataObject_Cast::sql('NULL');
$user->smsemail = null; $user->smsemail = DB_DataObject_Cast::sql('NULL');
// Throws exception on failure. Also performs it within a transaction. // Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($original); $user->updateWithKeys($original);
@ -416,7 +437,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return boolean does the number exist * @return boolean does the number exist
*/ */
function smsExists($sms) public function smsExists($sms)
{ {
$other = User::getKV('sms', $sms); $other = User::getKV('sms', $sms);
@ -432,7 +453,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function carrierSelect() public function carrierSelect()
{ {
$carrier = new Sms_carrier(); $carrier = new Sms_carrier();
@ -444,22 +465,33 @@ class SmssettingsAction extends SettingsAction
$this->element('label', array('for' => 'carrier'), _('Mobile carrier')); $this->element('label', array('for' => 'carrier'), _('Mobile carrier'));
$this->elementStart('select', array('name' => 'carrier', $this->elementStart('select', array('name' => 'carrier',
'id' => 'carrier')); 'id' => 'carrier'));
$this->element('option', array('value' => 0), $this->element(
// TRANS: Default option for mobile carrier dropdown menu in SMS settings. 'option',
_('Select a carrier')); ['value' => 0],
// TRANS: Default option for mobile carrier dropdown menu in SMS settings.
_('Select a carrier')
);
while ($carrier->fetch()) { while ($carrier->fetch()) {
$this->element('option', array('value' => $carrier->id), $this->element(
$carrier->name); 'option',
['value' => $carrier->id],
$carrier->name
);
} }
$this->elementEnd('select'); $this->elementEnd('select');
$this->element('p', 'form_guide', $this->element(
// TRANS: Form instructions for mobile carrier dropdown menu in SMS settings. 'p',
// TRANS: %s is an administrative contact's e-mail address. 'form_guide',
sprintf(_('Mobile carrier for your phone. '. // TRANS: Form instructions for mobile carrier dropdown menu in SMS settings.
'If you know a carrier that accepts ' . // TRANS: %s is an administrative contact's e-mail address.
'SMS over email but isn\'t listed here, ' . sprintf(
'send email to let us know at %s.'), _('Mobile carrier for your phone. ' .
common_config('site', 'email'))); 'If you know a carrier that accepts ' .
'SMS over email but isn\'t listed here, ' .
'send email to let us know at %s.'),
common_config('site', 'email')
)
);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
} }
@ -471,7 +503,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function confirmCode() public function confirmCode()
{ {
$code = $this->trimmed('code'); $code = $this->trimmed('code');
@ -488,7 +520,7 @@ class SmssettingsAction extends SettingsAction
* *
* @return void * @return void
*/ */
function removeIncoming() public function removeIncoming()
{ {
$user = common_current_user(); $user = common_current_user();
@ -499,7 +531,7 @@ class SmssettingsAction extends SettingsAction
$orig = clone($user); $orig = clone($user);
$user->incomingemail = null; $user->incomingemail = DB_DataObject_Cast::sql('NULL');
// Throws exception on failure. Also performs it within a transaction. // Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig); $user->updateWithKeys($orig);
@ -515,7 +547,7 @@ class SmssettingsAction extends SettingsAction
* *
* @see Emailsettings::newIncoming * @see Emailsettings::newIncoming
*/ */
function newIncoming() public function newIncoming()
{ {
$user = $this->scoped->getUser(); $user = $this->scoped->getUser();

View File

@ -1,35 +1,32 @@
<?php <?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social. If not, see <http://www.gnu.org/licenses/>.
/** /**
* StatusNet, the distributed open-source microblogging tool
*
* Data class for Conversations * Data class for Conversations
* *
* PHP version 5
*
* LICENCE: 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/>.
*
* @category Data * @category Data
* @package StatusNet * @package GNUsocial
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @author Mikael Nordfeldth <mmn@hethane.se> * @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2010 StatusNet Inc. * @copyright 2010 StatusNet Inc.
* @copyright 2009-2014 Free Software Foundation, Inc http://www.fsf.org * @copyright 2009-2014 Free Software Foundation, Inc http://www.fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
* @link http://status.net/
*/ */
if (!defined('GNUSOCIAL')) { exit(1); } defined('GNUSOCIAL') || die();
class Conversation extends Managed_DataObject class Conversation extends Managed_DataObject
{ {
@ -57,14 +54,14 @@ class Conversation extends Managed_DataObject
); );
} }
static public function beforeSchemaUpdate() public static function beforeSchemaUpdate()
{ {
$table = strtolower(get_called_class()); $table = strtolower(get_called_class());
$schema = Schema::get(); $schema = Schema::get();
$schemadef = $schema->getTableDef($table); $schemadef = $schema->getTableDef($table);
// 2016-01-06 We have to make sure there is no conversation with id==0 since it will screw up auto increment resequencing // 2016-01-06 We have to make sure there is no conversation with id==0 since it will screw up auto increment resequencing
if ($schemadef['fields']['id']['auto_increment']) { if ($schemadef['fields']['id']['auto_increment'] ?? false) {
// since we already have auto incrementing ('serial') we can continue // since we already have auto incrementing ('serial') we can continue
return; return;
} }
@ -91,7 +88,7 @@ class Conversation extends Managed_DataObject
* *
* @return Conversation the new conversation DO * @return Conversation the new conversation DO
*/ */
static function create(ActivityContext $ctx=null, $created=null) public static function create(ActivityContext $ctx = null, $created = null)
{ {
// Be aware that the Notice does not have an id yet since it's not inserted! // Be aware that the Notice does not have an id yet since it's not inserted!
$conv = new Conversation(); $conv = new Conversation();
@ -100,11 +97,16 @@ class Conversation extends Managed_DataObject
$conv->uri = $ctx->conversation; $conv->uri = $ctx->conversation;
$conv->url = $ctx->conversation_url; $conv->url = $ctx->conversation_url;
} else { } else {
$conv->uri = sprintf('%s%s=%s:%s=%s', $conv->uri = sprintf(
TagURI::mint(), '%s%s=%s:%s=%s',
'objectType', 'thread', TagURI::mint(),
'nonce', common_random_hexstr(8)); 'objectType',
$conv->url = null; // locally generated Conversation objects don't get static URLs stored 'thread',
'nonce',
common_random_hexstr(8)
);
// locally generated Conversation objects don't get static URLs stored
$conv->url = DB_DataObject_Cast::sql('NULL');
} }
// This insert throws exceptions on failure // This insert throws exceptions on failure
$conv->insert(); $conv->insert();
@ -112,7 +114,7 @@ class Conversation extends Managed_DataObject
return $conv; return $conv;
} }
static function noticeCount($id) public static function noticeCount($id)
{ {
$keypart = sprintf('conversation:notice_count:%d', $id); $keypart = sprintf('conversation:notice_count:%d', $id);
@ -132,7 +134,7 @@ class Conversation extends Managed_DataObject
return $cnt; return $cnt;
} }
static public function getUrlFromNotice(Notice $notice, $anchor=true) public static function getUrlFromNotice(Notice $notice, $anchor = true)
{ {
$conv = Conversation::getByID($notice->conversation); $conv = Conversation::getByID($notice->conversation);
return $conv->getUrl($anchor ? $notice->getID() : null); return $conv->getUrl($anchor ? $notice->getID() : null);

View File

@ -1,29 +1,32 @@
<?php <?php
/* // This file is part of GNU social - https://www.gnu.org/software/social
* StatusNet - the distributed open-source microblogging tool //
* Copyright (C) 2009-2010, StatusNet, Inc. // GNU social is free software: you can redistribute it and/or modify
* // it under the terms of the GNU Affero General Public License as published by
* This program is free software: you can redistribute it and/or modify // the Free Software Foundation, either version 3 of the License, or
* it under the terms of the GNU Affero General Public License as published by // (at your option) any later version.
* the Free Software Foundation, either version 3 of the License, or //
* (at your option) any later version. // GNU social is distributed in the hope that it will be useful,
* // but WITHOUT ANY WARRANTY; without even the implied warranty of
* This program is distributed in the hope that it will be useful, // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* but WITHOUT ANY WARRANTY; without even the implied warranty of // GNU Affero General Public License for more details.
* 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 GNU social. If not, see <http://www.gnu.org/licenses/>.
* 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/>.
*/
if (!defined('GNUSOCIAL')) { exit(1); }
/** /**
* @package OStatusPlugin * FeedSub handles low-level WebSub (PubSubHubbub/PuSH) subscriptions.
* @maintainer Brion Vibber <brion@status.net> * Higher-level behavior building OStatus stuff on top is handled
* under Ostatus_profile.
*
* @package OStatusPlugin
* @author Brion Vibber <brion@status.net>
* @copyright 2009-2010 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/ */
defined('GNUSOCIAL') || die();
/* /*
WebSub (previously PubSubHubbub/PuSH) subscription flow: WebSub (previously PubSubHubbub/PuSH) subscription flow:
@ -37,14 +40,8 @@ WebSub (previously PubSubHubbub/PuSH) subscription flow:
main/push/callback main/push/callback
hub sends us updates via POST hub sends us updates via POST
*/ */
/**
* FeedSub handles low-level WebSub (PubSubHubbub/PuSH) subscriptions.
* Higher-level behavior building OStatus stuff on top is handled
* under Ostatus_profile.
*/
class FeedSub extends Managed_DataObject class FeedSub extends Managed_DataObject
{ {
public $__table = 'feedsub'; public $__table = 'feedsub';
@ -96,7 +93,7 @@ class FeedSub extends Managed_DataObject
return $this->uri; return $this->uri;
} }
function getLeaseRemaining() public function getLeaseRemaining()
{ {
if (empty($this->sub_end)) { if (empty($this->sub_end)) {
return null; return null;
@ -118,8 +115,8 @@ class FeedSub extends Managed_DataObject
if (empty($this->huburi) if (empty($this->huburi)
&& (!common_config('feedsub', 'fallback_hub') && (!common_config('feedsub', 'fallback_hub')
|| $this->sub_state === 'nohub')) { || $this->sub_state === 'nohub')) {
// Here we have no huburi set. Also, either there is no // Here we have no huburi set. Also, either there is no
// fallback hub configured or sub_state is "nohub". // fallback hub configured or sub_state is "nohub".
return false; return false;
} }
return true; return true;
@ -180,7 +177,6 @@ class FeedSub extends Managed_DataObject
try { try {
// discover the hub uri // discover the hub uri
$feedsub->ensureHub(); $feedsub->ensureHub();
} catch (FeedSubNoHubException $e) { } catch (FeedSubNoHubException $e) {
// Only throw this exception if we can't handle huburi-less feeds // Only throw this exception if we can't handle huburi-less feeds
// (i.e. we have a fallback hub or we can do feed polling (nohub) // (i.e. we have a fallback hub or we can do feed polling (nohub)
@ -263,7 +259,7 @@ class FeedSub extends Managed_DataObject
*/ */
public function subscribe($rediscovered=false) public function subscribe($rediscovered=false)
{ {
if ($this->sub_state && $this->sub_state != 'inactive') { if ($this->sub_state !== 'inactive') {
common_log(LOG_WARNING, sprintf('Attempting to (re)start WebSub subscription to %s in unexpected state %s', $this->getUri(), $this->sub_state)); common_log(LOG_WARNING, sprintf('Attempting to (re)start WebSub subscription to %s in unexpected state %s', $this->getUri(), $this->sub_state));
} }
@ -276,7 +272,7 @@ class FeedSub extends Managed_DataObject
if (common_config('feedsub', 'fallback_hub')) { if (common_config('feedsub', 'fallback_hub')) {
// No native hub on this feed? // No native hub on this feed?
// Use our fallback hub, which handles polling on our behalf. // Use our fallback hub, which handles polling on our behalf.
} else if (common_config('feedsub', 'nohub')) { } elseif (common_config('feedsub', 'nohub')) {
// For this to actually work, we'll need some polling mechanism. // For this to actually work, we'll need some polling mechanism.
// The FeedPoller plugin should take care of it. // The FeedPoller plugin should take care of it.
return; return;
@ -298,7 +294,8 @@ class FeedSub extends Managed_DataObject
* *
* @throws ServerException if feed state is not valid * @throws ServerException if feed state is not valid
*/ */
public function unsubscribe() { public function unsubscribe()
{
if ($this->sub_state != 'active') { if ($this->sub_state != 'active') {
common_log(LOG_WARNING, sprintf('Attempting to (re)end WebSub subscription to %s in unexpected state %s', $this->getUri(), $this->sub_state)); common_log(LOG_WARNING, sprintf('Attempting to (re)end WebSub subscription to %s in unexpected state %s', $this->getUri(), $this->sub_state));
} }
@ -344,7 +341,7 @@ class FeedSub extends Managed_DataObject
*/ */
public function garbageCollect() public function garbageCollect()
{ {
if ($this->sub_state == '' || $this->sub_state == 'inactive') { if ($this->sub_state === 'inactive') {
// No active WebSub subscription, we can just leave it be. // No active WebSub subscription, we can just leave it be.
return true; return true;
} }
@ -366,12 +363,12 @@ class FeedSub extends Managed_DataObject
return true; return true;
} }
static public function renewalCheck() public static function renewalCheck()
{ {
$fs = new FeedSub(); $fs = new FeedSub();
// the "" empty string check is because we historically haven't saved unsubscribed feeds as NULL $fs->whereAdd('sub_end IS NOT NULL AND sub_end < (CURRENT_TIMESTAMP + INTERVAL 1 DAY)');
$fs->whereAdd('sub_end IS NOT NULL AND sub_end!="" AND sub_end < NOW() + INTERVAL 1 day'); // find can be both false and 0, depending on why nothing was found
if (!$fs->find()) { // find can be both false and 0, depending on why nothing was found if (!$fs->find()) {
throw new NoResultException($fs); throw new NoResultException($fs);
} }
return $fs; return $fs;
@ -437,10 +434,10 @@ class FeedSub extends Managed_DataObject
if ($status == 202 || $status == 204) { if ($status == 202 || $status == 204) {
common_log(LOG_INFO, __METHOD__ . ': sub req ok, awaiting verification callback'); common_log(LOG_INFO, __METHOD__ . ': sub req ok, awaiting verification callback');
return; return;
} else if ($status >= 200 && $status < 300) { } elseif ($status >= 200 && $status < 300) {
common_log(LOG_ERR, __METHOD__ . ": sub req returned unexpected HTTP $status: " . $response->getBody()); common_log(LOG_ERR, __METHOD__ . ": sub req returned unexpected HTTP $status: " . $response->getBody());
$msg = sprintf(_m("Unexpected HTTP status: %d"), $status); $msg = sprintf(_m("Unexpected HTTP status: %d"), $status);
} else if ($status == 422 && !$rediscovered) { } elseif ($status == 422 && !$rediscovered) {
// Error code regarding something wrong in the data (it seems // Error code regarding something wrong in the data (it seems
// that we're talking to a WebSub hub at least, so let's check // that we're talking to a WebSub hub at least, so let's check
// our own data to be sure we're not mistaken somehow, which // our own data to be sure we're not mistaken somehow, which
@ -482,7 +479,8 @@ class FeedSub extends Managed_DataObject
if ($lease_seconds > 0) { if ($lease_seconds > 0) {
$this->sub_end = common_sql_date(time() + $lease_seconds); $this->sub_end = common_sql_date(time() + $lease_seconds);
} else { } else {
$this->sub_end = null; // Backwards compatibility to StatusNet (PuSH <0.4 supported permanent subs) // Backwards compatibility to StatusNet (PuSH <0.4 supported permanent subs)
$this->sub_end = DB_DataObject_Cast::sql('NULL');
} }
$this->modified = common_sql_now(); $this->modified = common_sql_now();
@ -498,11 +496,10 @@ class FeedSub extends Managed_DataObject
{ {
$original = clone($this); $original = clone($this);
// @fixme these should all be null, but DB_DataObject doesn't save null values...????? $this->secret = DB_DataObject_Cast::sql('NULL');
$this->secret = ''; $this->sub_state = 'inactive';
$this->sub_state = ''; $this->sub_start = DB_DataObject_Cast::sql('NULL');
$this->sub_start = ''; $this->sub_end = DB_DataObject_Cast::sql('NULL');
$this->sub_end = '';
$this->modified = common_sql_now(); $this->modified = common_sql_now();
return $this->update($original); return $this->update($original);
@ -544,7 +541,6 @@ class FeedSub extends Managed_DataObject
} }
$this->receiveFeed($post); $this->receiveFeed($post);
} catch (FeedSubBadPushSignatureException $e) { } catch (FeedSubBadPushSignatureException $e) {
// We got a signature, so something could be wrong. Let's check to see if // We got a signature, so something could be wrong. Let's check to see if
// maybe upstream has switched to another hub. Let's fetch feed and then // maybe upstream has switched to another hub. Let's fetch feed and then
@ -628,7 +624,6 @@ class FeedSub extends Managed_DataObject
throw new FeedSubBadPushSignatureException('Incoming WebSub push signature did not match expected HMAC hash.'); throw new FeedSubBadPushSignatureException('Incoming WebSub push signature did not match expected HMAC hash.');
} }
return true; return true;
} else { } else {
common_log(LOG_ERR, sprintf(__METHOD__.': ignoring WebSub push with bogus HMAC==', _ve($hmac))); common_log(LOG_ERR, sprintf(__METHOD__.': ignoring WebSub push with bogus HMAC==', _ve($hmac)));
} }