Bug(バグ) #4035
未完了メールアドレスの登録がなく,同時にregister_tokenの登録が無いメンバーがmember_configテーブルに存在するとopAuthMailAddressPluginによる新規登録がおこなえない
0%
説明
Overview (現象)¶
OpenPNE 3.8.21 において,「member_config」テーブル上に,下記条件を同時に満たすメンバーが存在すると,招待メールのURLをクリックしても,500エラーとなり,メンバー登録を完了できない。
【条件】*1
・member_configテーブル上にname=pc_addressのレコードが空である(メールアドレスが登録されていない)
・member_configテーブル上にname=register_tokenのレコードを持たない(opAuthMailAddressPluginによる仮登録状態ではない)*1) opAuthSocialPlugin使用時等,メールアドレスの登録が必須でない場合に,このようなメンバーが作成されます。
そのため,opAuthSocialPluginとopAuthMailAddressPluginを同時に有効にすると,opAuthSocialPluginは正常に機能しますが,opAuthMailAddressPluginは新規登録できない状態になります。
Causes (原因)¶
以下,エラー発生箇所のコード追跡。¶
file: lib/action/opMemberAction.class.php
line: 174
method: opMemberAction::executeRegisterInput(opWebRequest $request)
$member = $this->getUser()->setRegisterToken($this->token);
file: lib/user/opSecurityUser.class.php
line: 431
method: opSecurityUser::setRegisterToken($token)
$member = Doctrine::getTable('Member')->findByValidRegisterToken($token, $mailTypes);
file: lib/model/doctrine/MemberTable.class.php
line: 156
method: MemberTable::findByValidRegisterToken($token, $configNames)
public function findByValidRegisterToken($token, $configNames)
{
$member = $this->findByRegisterToken($token);
if (!$member)
{
return false;
}
$configTable = Doctrine::getTable('MemberConfig');
$query = $configTable->createQuery('m');
foreach ($configNames as $configName)
{
$hash = $configTable->generateNameValueHash($configName, $member->getConfig($configName));
$query->orWhere('m.name_value_hash = ?', $hash);
}
$configs = $query->fetchArray();
$memberIds = array();
$updateTimes = array();
foreach ($configs as $config)
{
$memberIds[] = $memberId = $config['member_id'];
$updateTimes[] = $configTable
->createQuery('m')
->where('m.member_id = ?', $memberId)
->AndWhere('m.name = "register_token"')
->fetchOne()
->getUpdatedAt();
}
array_multisort($updateTimes, $memberIds);
if ($member->getId() !== $memberIds[count($memberIds)-1])
{
return false;
}
return $member;
}
エラー発生箇所¶
file: lib/model/doctorine/MemberTable.class.php
line: 182
method: MemberTable::findByValidRegisterToken($token, $configNames)
$updateTimes[] = $configTable->createQuery('m')->where('m.member_id = ?', $memberId)->AndWhere('m.name = "register_token"')->fetchOne()->getUpdatedAt();
エラー発生理由¶
'm.name = "register_token"'の条件に合致するレコードが存在しないため,fetchOne()にて500エラーとなる。
Way to fix (修正内容) [DRAFT] 【案】¶
【注】当方,PHP,SQLおよびsymfonyに疎いため,Doctrineにおけるレコード存在の確認の方法が分からず,とりあえずこれで動いたという方法を記しています。
そのため,本来のこの関数の在り方に沿った修正であるか不明です。関数の在り方や呼び出し方等含め,再確認いただければと思います。
(なお,現行のコードでは169行目で$query->orWhereで繋いでいるためにname=pc_addressが空欄のレコードは無条件に含まれることとなっています。)
下記部分を以下のように修正
file: lib/model/doctorine/MemberTable.class.php
line: 175-184
method: MemberTable::findByValidRegisterToken($token, $configNames)
foreach ($configs as $config)
{
$memberIds[] = $memberId = $config['member_id'];
$m_rt = $configTable
->createQuery('m')
->where('m.member_id = ?', $memberId)
->AndWhere('m.name = "register_token"')->fetchArray();
if ($m_rt){
$updateTimes[] = $configTable
->createQuery('m')
->where('m.member_id = ?', $memberId)
->AndWhere('m.name = "register_token"')
->fetchOne()
->getUpdatedAt();
} else {
array_pop($memberIds);
}
}
関連するチケット¶
表示するデータがありません