public function perform() { $args = $this->args; if (empty($args['accountId']) || empty($args['key']) || empty($args['header'])) { ResqueUtil::log(['status' => 'fail to export member', 'message' => 'missing params', 'args' => $args]); return false; } Yii::$app->language = empty($args['language']) ? LanguageUtil::DEFAULT_LANGUAGE : $args['language']; $accountId = new \MongoId($args['accountId']); $header = $args['header']; // get member's customized properties $memberProperties = MemberProperty::getByAccount($accountId); foreach ($memberProperties as $memberProperty) { if ($memberProperty->isDefault) { $header[$memberProperty->name] = Yii::t('member', $memberProperty->name); } else { $header[$memberProperty->name] = $memberProperty->name; } } $socialAccountsMap = []; $account = Account::findByPk($accountId); $channelIds = Channel::getEnableChannelIds($accountId); if (!empty($channelIds)) { $socialAccounts = \Yii::$app->weConnect->getAccounts($channelIds); foreach ($socialAccounts as $socialAccount) { $socialAccountsMap[$socialAccount['id']] = $socialAccount['name']; } } $cardMap = []; $cards = MemberShipCard::getByAccount($accountId); foreach ($cards as $card) { $cardMap[(string) $card->_id] = $card->name; } $condition = unserialize($args['condition']); //get properties $memberProperties = MemberProperty::findAll(['accountId' => $accountId]); $base = ['cardMap' => $cardMap, 'socialAccountsMap' => $socialAccountsMap, 'memberProperties' => $memberProperties]; $fileName = $args['key']; $filePath = ExcelUtil::getFile($fileName, 'csv'); $orderBy = Member::normalizeOrderBy($args['params']); $object = Member::find(); $classFunction = '\\backend\\modules\\member\\models\\Member::preProcessMemberData'; ExcelUtil::processMultiData($header, $filePath, $base, $condition, $object, $classFunction, [], $orderBy); $hashKey = ExcelUtil::setQiniuKey($filePath, $fileName); if ($hashKey) { //notice frontend the job is finished \Yii::$app->tuisongbao->triggerEvent(Message::EVENT_EXPORT_FINISH, ['key' => $fileName], [Message::CHANNEL_GLOBAL . $args['accountId']]); return true; } else { return false; } }
public function perform() { $args = $this->args; $date = empty($args['date']) ? '' : $args['date']; $datetime = TimeUtil::getDatetime($date); $accountId = $args['accountId']; //Assume that the subChannel is the secode element in properties $propertyKey = $args['properties'][1]; $memberProperty = MemberProperty::findOne(['propertyId' => $propertyKey]); if ($memberProperty != null) { return ModelStatsMemberPropTradeCodeQuarterly::generateByYearAndQuarter((string) $memberProperty['_id'], $accountId, $datetime); } else { ResqueUtil::log("Fail to get memberProperty with propertyId {$propertyKey}"); } return false; }
/** * @return array or false * @param $accountId, string * @param $isDefault, boolean,null means to get all properties,true means to get default property,false means to get properties whitch member custom properties */ public function all($isDefault = null) { if (true === $isDefault) { $where = ['accountId' => $this->accountId, 'isDefault' => true]; } else { if (false === $isDefault) { $where = ['accountId' => $this->accountId, 'isDefault' => false]; } else { $where['accountId'] = $this->accountId; } } $memberProperty = ModelMemberProperty::findAll($where); if (empty($memberProperty)) { return []; } else { return $memberProperty; } }
private static function _setStatsMemberPropTradeQuarterly($startTime, $endTime, $args) { //Assume that the subChannel is the secode element in properties $propertyKey = $args['properties'][1]; $memberProperty = MemberProperty::findOne(['propertyId' => $propertyKey]); if (!empty($memberProperty)) { $startQuarter = TimeUtil::getQuarter($startTime); $endQuarter = TimeUtil::getQuarter($endTime); for ($quarter = $startQuarter; $quarter <= $endQuarter; ++$quarter) { $year = date('Y', $startTime); $condition = ['accountId' => $args['accountId'], 'year' => $year, 'quarter' => $quarter]; StatsMemberPropTradeQuarterly::deleteAll($condition); self::generateStatsMemberPropTradeQuarterlyData((string) $memberProperty['_id'], $condition); LogUtil::info(['message' => $quarter . ' :Run StatsMemberPropTradeQuarterly'], 'update_job'); } } else { LogUtil::info(['message' => 'Can not find this propertyId:' . $propertyKey], 'update_job'); } }
public function perform() { $args = $this->args; if (empty($args['accountId']) || empty($args['properties'][0])) { ResqueUtil::log('Missing required arguments accountId or properties!'); return false; } $accountId = new MongoId($args['accountId']); $property = $args['properties'][0]; $memberProperty = MemberProperty::getByPropertyId($accountId, $property); if (empty($memberProperty)) { ResqueUtil::log('Can not find member property with propertyId:' . $property); return false; } $date = empty($args['date']) ? '' : $args['date']; $date = TimeUtil::getDatetime($date); $year = date('Y', $date); $quarter = TimeUtil::getQuarter($date); self::generateData($memberProperty, $property, $year, $quarter, $accountId); return true; }
public function perform() { $args = $this->args; if (empty($args['accountId']) || empty($args['properties'][0])) { ResqueUtil::log('Missing required arguments accountId or properties!'); return false; } $accountId = new \MongoId($args['accountId']); $property = $args['properties'][0]; $memberProperty = MemberProperty::findOne(['propertyId' => $property, 'accountId' => $accountId]); if (empty($memberProperty)) { ResqueUtil::log('Can not find member property with propertyId:' . $property); return false; } $date = empty($args['date']) ? '' : $args['date']; $date = TimeUtil::getDatetime($date); $month = date('Y-m', $date); $startDate = strtotime($month); $endDate = strtotime(date('Y-m', strtotime('+1 month', $date))); $raw = Member::getCollection()->aggregate([['$unwind' => '$properties'], ['$match' => ['createdAt' => ['$gte' => new \MongoDate($startDate), '$lt' => new \MongoDate($endDate)], 'properties.id' => $memberProperty->_id, 'accountId' => $accountId]], ['$group' => ['_id' => '$properties.value', 'total' => ['$sum' => 1]]]]); foreach ($raw as $item) { $total = $item['total']; $propValue = $item['_id']; // save the stats member property monthly $statsMemberPropMonthly = ModelStatsMemberPropMonthly::findOne(['propId' => $property, 'propValue' => $propValue, 'month' => $month, 'accountId' => $accountId]); if (empty($statsMemberPropMonthly)) { $statsMemberPropMonthly = new ModelStatsMemberPropMonthly(); $statsMemberPropMonthly->propId = $property; $statsMemberPropMonthly->propValue = $propValue; $statsMemberPropMonthly->month = $month; $statsMemberPropMonthly->accountId = $accountId; } $statsMemberPropMonthly->total = $total; ResqueUtil::log($statsMemberPropMonthly->attributes); $statsMemberPropMonthly->save(); } return true; }
public function validateProperties($attribute) { if ($attribute != 'properties' || $this->name != self::NAME_PERFECT_INFO) { return true; } $properties = $this->{$attribute}; if (empty($properties)) { throw new InvalidParameterException(['rulePropertiesRequired' => \Yii::t('common', 'required_filed')]); } $visablePropertyCount = MemberProperty::count(['_id' => ['$in' => $properties], 'isVisible' => true]); if ($visablePropertyCount != count($properties)) { throw new InvalidParameterException(['rulePropertiesRequired' => \Yii::t('member', 'rule_property_error')]); } }
/** * Follower bind to be a member. * * <b>Request Type</b>: POST<br/><br/> * <b>Request Endpoint</b>:http://{server-domain}/api/mobile/bind<br/><br/> * <b>Response Content-type</b>: application/json<br/><br/> * <b>Summary</b>: This api is used for follower bind. * <br/><br/> * * <b>Request Params</b>:<br/> * mobile: string<br/> * openId: string<br/> * unionId: string<br/> * channelId: string<br/> * captcha: string<br/> * <br/><br/> * * <b>Response Params:</b><br/> * <br/><br/> * * <br/><br/> * * <b>Response Example</b>:<br/> * <pre> * { * "message": "OK", * "data": "http://wm.com?memberId=55d29e86d6f97f72618b4569" * </pre> */ public function actionBind() { //set language zh_cn when bind Yii::$app->language = LanguageUtil::LANGUAGE_ZH; $params = $this->getParams(); if (empty($params['mobile']) || empty($params['openId']) || empty($params['channelId']) || empty($params['captcha'])) { throw new BadRequestHttpException('missing param'); } $isTest = false; if ($params['mobile'] == self::TEST_PHONE && $params['captcha'] == self::TEST_CODE) { $isTest = true; } else { $this->attachBehavior('CaptchaBehavior', new CaptchaBehavior()); $this->checkCaptcha($params['mobile'], $params['captcha']); } //get accountId $openId = $params['openId']; $channel = Channel::getEnableByChannelId($params['channelId']); $origin = $channel->origin; $accountId = $channel->accountId; //create accessToken $token = Token::createForMobile($accountId); if (empty($token['accessToken'])) { throw new ServerErrorHttpException('Failed to create token for unknown reason.'); } $accessToken = $token['accessToken']; $this->setAccessToken($accessToken); //if member has bind if (empty($params['unionId'])) { $member = Member::getByOpenId($openId); } else { $unionId = $params['unionId']; $member = Member::getByUnionid($unionId); } if (!empty($member)) { $memberId = (string) $member->_id; $url = $this->buildBindRedirect($memberId, $params); return ['message' => 'OK', 'data' => $url]; } //check mobile has been bind $member = Member::getByMobile($params['mobile'], new \MongoId($accountId)); if (!empty($member)) { throw new InvalidParameterException(['phone' => Yii::t('common', 'phone_has_been_bound')]); } $follower = Yii::$app->weConnect->getFollowerByOriginId($openId, $params['channelId']); $originScene = empty($follower['firstSubscribeSource']) ? '' : $follower['firstSubscribeSource']; //init avatar and location $avatar = !empty($follower['headerImgUrl']) ? $follower['headerImgUrl'] : Yii::$app->params['defaultAvatar']; $location = []; !empty($follower['city']) ? $location['city'] = $follower['city'] : null; !empty($follower['province']) ? $location['province'] = $follower['province'] : null; !empty($follower['country']) ? $location['country'] = $follower['country'] : null; LogUtil::info(['message' => 'get follower info', 'follower' => $follower], 'channel'); //init member properties $memberProperties = MemberProperty::getByAccount($accountId); $propertyMobile = []; $propertyGender = []; $propertyName = []; $properties = []; foreach ($memberProperties as $memberProperty) { if ($memberProperty['name'] == Member::DEFAULT_PROPERTIES_MOBILE) { $propertyMobile['id'] = $memberProperty['_id']; $propertyMobile['name'] = $memberProperty['name']; $propertyMobile['value'] = $params['mobile']; $properties[] = $propertyMobile; } if ($memberProperty['name'] == Member::DEFAULT_PROPERTIES_GENDER) { $propertyGender['id'] = $memberProperty['_id']; $propertyGender['name'] = $memberProperty['name']; $propertyGender['value'] = !empty($follower['gender']) ? strtolower($follower['gender']) : 'male'; $properties[] = $propertyGender; } if ($memberProperty['name'] == Member::DEFAULT_PROPERTIES_NAME) { $propertyName['id'] = $memberProperty['_id']; $propertyName['name'] = $memberProperty['name']; $propertyName['value'] = $follower['nickname']; $properties[] = $propertyName; } } //get default card $card = MemberShipCard::getDefault($accountId); $memberId = new \MongoId(); $memberAttribute = ['$set' => ['_id' => $memberId, 'avatar' => $avatar, 'cardId' => $card['_id'], 'location' => $location, 'score' => 0, 'socialAccountId' => $params['channelId'], 'properties' => $properties, 'openId' => $openId, 'origin' => $origin, 'originScene' => $originScene, 'unionId' => empty($unionId) ? '' : $unionId, 'accountId' => $accountId, 'cardNumber' => Member::generateCardNumber($card['_id']), 'cardProvideTime' => new \MongoDate(), 'createdAt' => new \MongoDate(), 'socials' => [], 'isDeleted' => false]]; if (!$isTest) { $result = Member::updateAll($memberAttribute, ['openId' => $openId], ['upsert' => true]); } else { $result = true; } if ($result) { // reword score first bind card $this->attachBehavior('MemberBehavior', new MemberBehavior()); $this->updateItemByScoreRule(Member::findByPk($memberId)); Yii::$app->qrcode->create(Yii::$app->request->hostInfo, Qrcode::TYPE_MEMBER, $memberId, $accountId); $memberId = (string) $memberId; $url = $this->buildBindRedirect($memberId, $params); return ['message' => 'OK', 'data' => $url]; } else { LogUtil::error(['error' => 'member save error', 'params' => Json::encode($member)], 'member'); throw new ServerErrorHttpException("bind fail"); } }
public static function webhookEvent($member) { $property = MemberProperty::findOne(['name' => Member::DEFAULT_PROPERTIES_MOBILE, 'accountId' => $member->accountId]); $phone = ''; if (!empty($property) && !empty($member->properties)) { foreach ($member->properties as $memberProperty) { if ((string) $memberProperty['id'] === (string) $property->_id) { $phone = $memberProperty['value']; break; } } } $triggerData = ['type' => Webhook::EVENT_MEMBER_CREATED, 'account_id' => (string) $member->accountId, 'member_id' => (string) $member->_id, 'phone' => $phone, 'origin' => Member::PORTAL, 'created_at' => MongodbUtil::MongoDate2String($member->createdAt, \DateTime::ATOM)]; Yii::$app->webhook->triggerEvent($triggerData); }
/** * Order member properties * <b>Request Type: </b>PUT<br/> * <b>Request Endpoint: </b>http://{{server-domain}}/api/common/member-property/order<br/> * <b>Summary</b> This api is for ordering property for member. * <b>Request Parameters</b><br/> * * <pre> * { * "54a8efe6b81374334e8b4567": 3, * "54a8efe6b81374334e8b4568": 2, * "54a8efe6b81374334e8b4569": 1, * "54a8efe6b81374334e8b4570": 4, * } * </pre> */ public function actionOrder() { $orderMap = $this->getParams(); foreach ($orderMap as $id => $order) { if (!MemberProperty::updateAll(['order' => $order], ['_id' => $id])) { throw new ServerErrorHttpException("Failed to save property order with id " . $id); } } Yii::$app->getResponse()->setStatusCode(204); }
/** * Create default member properties */ public static function createDefaultMemberProperties($accountId) { $now = time(); MemberProperty::getCollection()->batchInsert([["order" => 1, "name" => "name", "type" => MemberProperty::TYPE_INPUT, "defaultValue" => "", "isRequired" => true, "isUnique" => true, "isVisible" => true, "isDefault" => true, "accountId" => $accountId, "createdAt" => new \MongoDate($now), "updatedAt" => new \MongoDate($now), "isDeleted" => false], ["order" => 2, "name" => "tel", "type" => MemberProperty::TYPE_INPUT, "defaultValue" => "", "isRequired" => true, "isUnique" => true, "isVisible" => true, "isDefault" => true, "accountId" => $accountId, "createdAt" => new \MongoDate($now), "updatedAt" => new \MongoDate($now), "isDeleted" => false], ["order" => 3, "name" => "gender", "type" => MemberProperty::TYPE_RADIO, "defaultValue" => "male", "options" => ["male", "female"], "isRequired" => false, "isUnique" => false, "isVisible" => true, "isDefault" => true, "accountId" => $accountId, "createdAt" => new \MongoDate($now), "updatedAt" => new \MongoDate($now), "isDeleted" => false], ["order" => 4, "name" => "birthday", "type" => MemberProperty::TYPE_DATE, "defaultValue" => "", "isRequired" => true, "isUnique" => false, "isVisible" => true, "isDefault" => true, "accountId" => $accountId, "createdAt" => new \MongoDate($now), "updatedAt" => new \MongoDate($now), "isDeleted" => false], ["order" => 5, "name" => "email", "type" => MemberProperty::TYPE_EMAIL, "defaultValue" => "", "isRequired" => false, "isUnique" => true, "isVisible" => true, "isDefault" => true, "accountId" => $accountId, "createdAt" => new \MongoDate($now), "updatedAt" => new \MongoDate($now), "isDeleted" => false]]); }
private static function _getPropertyId($condition) { $propertyIds = MemberProperty::find()->select(['_id'])->where($condition)->all(); $propertyIdStrs = []; if (empty($propertyIds)) { LogUtil::error(['message' => 'Run update StatsMemberCampaignLog fail, because the propertyIds is empty', 'condition' => $condition], 'resque'); } else { foreach ($propertyIds as $propertyId) { $propertyIdStrs[] = (string) $propertyId['_id']; } } return $propertyIdStrs; }
public static function getMobileVar($params) { if (empty($params['memberId'])) { throw new BadRequestHttpException('missing params'); } $type = $params['type']; if (!in_array($type, [self::REDEMPTION_TYPE, self::PROMOCODE_TYPE])) { throw new BadRequestHttpException('type is invaild'); } $params['memberId'] = new \MongoId($params['memberId']); $member = Member::getMemberInfo($params['memberId'], ['name', 'gender', 'email', 'tel', 'birthday', 'score']); if ('male' == $member['gender']) { $gender = '男'; } else { $gender = '女'; } $product = $promoCode = ''; if (!empty($params['data'])) { //create product list foreach ($params['data'] as $data) { if (isset($data['productName'])) { $product .= $data['productName'] . ','; } else { $promoCode = implode(',', $params['data']); break; } } $product = rtrim($product, ','); } $memberInfo = Member::findByPk($params['memberId']); $vars = ['address' => !empty($params['address']) ? $params['address'] : '', 'pointBalance' => !isset($memberInfo->score) ? 0 : $memberInfo->score, 'product' => $product, 'promoCode' => $promoCode, 'username' => $member['name'], 'gender' => $gender, 'email' => $member['email'], 'phone' => $member['tel'], 'birthday' => date('Y-m-d', $member['birthday'] / TimeUtil::MILLI_OF_SECONDS), 'total' => empty($params['total']) ? 0 : $params['total'], 'totalScore' => empty($params['totalScore']) ? 0 : $params['totalScore'], 'number' => count($params['data']), 'amount' => empty($params['usedScore']) ? 0 : $params['usedScore']]; //to suport member propertyId $properties = MemberProperty::getMemberProperty($memberInfo->accountId, $memberInfo->properties); $vars = array_merge($vars, $properties); return $vars; }
public static function getPropertyIds($condition) { $propertyIds = MemberProperty::find()->select(['_id'])->where($condition)->all(); $propertyIdStrs = []; foreach ($propertyIds as $propertyId) { $propertyIdStrs[] = (string) $propertyId['_id']; } return $propertyIdStrs; }
private function _validateProperty($member) { $idValueMap = $member->getPropertyMap(); //get all property $memberProperties = MemberProperty::getByAccount($member->accountId); foreach ($memberProperties as $memberProperty) { $id = $memberProperty->_id . ''; //validate require if ($memberProperty->isRequired && !isset($idValueMap[$id])) { throw new InvalidParameterException([$id => \Yii::t('member', 'require_filed')]); } //validate unique if ($memberProperty->isUnique && isset($idValueMap[$id]) && $idValueMap[$id] != "") { $uniqueMember = Member::getByProperty($memberProperty->_id, $idValueMap[$id]); if (!empty($uniqueMember) && (empty($member->_id) || !empty($member->_id) && $uniqueMember->_id != $member->_id)) { if ($memberProperty->name == 'tel') { throw new InvalidParameterException([$id => \Yii::t('member', 'unique_tel_filed')]); } else { throw new InvalidParameterException([$id => \Yii::t('member', 'unique_filed')]); } } } //validate email if ($memberProperty->name === Member::DEFAULT_PROPERTIES_EMAIL && !empty($idValueMap[$id]) && !StringUtil::isEmail($idValueMap[$id])) { throw new InvalidParameterException([$id => \Yii::t('member', 'email_format_error')]); } } }
public function perform() { # Run task $args = $this->args; if (empty($args['locationPath']) || empty($args['accountId']) || empty($args['filePath']) || empty($args['qiniuBucket']) || empty($args['fileName'])) { ResqueUtil::log(['error' => 'missing params in MemberCheckCode', 'args' => $args]); } //get qiniu file $qiniuFile = Yii::$app->curl->get($args['filePath'], [], false); if (false === file_put_contents($args['locationPath'], $qiniuFile)) { ResqueUtil::log(['message' => 'Fail to get file from qiniu in MemberCheckCode class', 'args' => $args]); return false; } $phpreader = new \PHPExcel_Reader_Excel2007(); $filePath = $args['locationPath']; if (!$phpreader->canRead($filePath)) { $phpreader = new \PHPExcel_Reader_Excel5(); if (!$phpreader->canRead($filePath)) { $phpreader = \PHPExcel_IOFactory::createReader('CSV')->setDelimiter(',')->setInputEncoding('GBK')->setEnclosure('"')->setLineEnding("\r\n")->setSheetIndex(0); if (!$phpreader->canRead($filePath)) { ResqueUtil::log(['error' => 'file can not read in MemberCheckCode', 'args' => $args]); return false; } } } $phpexcel = $phpreader->load($filePath); //read the first of table with excel. $currentSheet = $phpexcel->getSheet(0); //get the largest column $allColumn = $currentSheet->getHighestColumn(); //get total row num $allRow = $currentSheet->getHighestRow(); //make a key to be called a name for redis set $cacheSetInsert = self::SET_HEAD_INSERT . md5($args['accountId'] . "_" . $args['fileName']); $cacheSetUpdate = self::SET_HEAD_UPDATE . md5($args['accountId'] . "_" . $args['fileName']); //make a key to be called a name for redis hash $cacheHash = md5($args['accountId'] . "_" . $args['fileName']); $ignorePropertyKey = self::MEMBER_FILE_IGNORE . $cacheHash; $missPropertyKey = self::MEMBER_FILE_MISS . $cacheHash; $repeatTitleKey = self::MEMBER_REPEAT_TITLE . $cacheHash; //the key for wrong number for store in redis $wrongKey = self::MEMBER_WRONG; //the key for right number for store in redis $rightKey = self::MEMBER_RIGHT; $total = $wrong = $right = $rightInsert = $rightUpdate = 0; $redis = Yii::$app->cache->redis; $redis->expire($cacheHash, self::EXPIRE); $title = []; // verify the member of phone. $re = "/^0?1[0-9]{10}\$/"; $reTel = "/^09[0-9]{8}\$/"; // verify the member of birthday (YYYY-MM-DD) $reDateOne = "/^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)\$/"; // define the default of property. $defaultProperties = ['name' => 'name', 'mobile' => 'tel', 'gender' => 'gender', 'birthday' => 'birthday', 'email' => 'email']; $dbExistProperties = ['name' => 'Name', 'tel' => 'Mobile', 'gender' => 'Gender', 'birthday' => 'Birthday', 'email' => 'Email']; $ignoreProperties = []; $columnElements = []; // all elements of a column $property = []; $titles = []; $realTitles = []; $rowIndex = 1; $defaulyProperties = []; $properties = []; $requiredProperty = []; $existsTitle = []; if ($allRow <= 1) { ResqueUtil::log(['error' => 'the file of excel hasn`t data']); $array = ['value' => null, 'rows' => null, 'cols' => null, 'property' => null, 'wrongNum' => self::MEMBER_NO_DATA]; $this->storeError($redis, $array, $args); return false; } // get title of excel. $mapTitlePropertyId = []; $titleIndexClo = -1; for ($columnIndex = 'A'; $columnIndex <= $allColumn; $columnIndex++) { $titleIndexClo++; $titleName = strtolower(trim((string) $currentSheet->getCell($columnIndex . $rowIndex)->getValue())); if (empty($titleName)) { continue; } if (array_key_exists((string) $titleName, $defaultProperties)) { $findValues = $defaultProperties[(string) $titleName]; $propertyValueOne = MemberProperty::findOne(['name' => new \MongoRegex("/^{$findValues}\$/i"), 'accountId' => new MongoId($args['accountId']), 'isDeleted' => false]); $property[] = empty($propertyValueOne) ? [] : $propertyValueOne; $titles[] = empty($defaultProperties[(string) $titleName]) ? "" : $defaultProperties[(string) $titleName]; $realTitles[] = empty($propertyValueOne) ? '' : (string) $propertyValueOne['name']; $mapTitlePropertyId[$titleName] = $propertyValueOne['_id']; } else { $findValue = (string) $titleName; $propertyValueOne = MemberProperty::findOne(['propertyId' => new \MongoRegex("/^{$findValue}\$/i"), 'accountId' => new MongoId($args['accountId']), 'isDeleted' => false]); $property[] = empty($propertyValueOne) ? [] : $propertyValueOne; $titles[] = empty((string) $titleName) ? '' : (string) $titleName; $realTitles[] = empty($propertyValueOne) ? '' : (string) $propertyValueOne['propertyId']; $mapTitlePropertyId[$titleName] = $propertyValueOne['_id']; } if (!in_array((string) $titleName, $title)) { $title[] = (string) $titleName; } else { $existsTitle[] = (string) $titleName; } } // Get index of mobile in titles. $mobileIndex = array_search(Member::DEFAULT_PROPERTIES_MOBILE, $titles); $mobileColumn = \PHPExcel_Cell::stringFromColumnIndex($mobileIndex); $mobiles = []; // Verify if the title is repeated. if (count($existsTitle) > 0) { ResqueUtil::log(['error' => 'the title is repeated', 'args' => ['existsTitle' => $existsTitle]]); $array = ['value' => null, 'rows' => null, 'cols' => null, 'property' => null, 'wrongNum' => self::MEMBER_TITLE_REPEATED]; $this->storeError($redis, $array, $args); $redis->sadd($repeatTitleKey, serialize($existsTitle)); unset($existsTitle); return false; } // get all property. $defaulyProperty = MemberProperty::find()->select(['_id', 'name'])->from('memberProperty')->where(['isRequired' => true, 'isVisible' => true, 'isDefault' => true, 'isDeleted' => false, 'accountId' => new MongoId($args['accountId'])])->all(); foreach ($defaulyProperty as $data) { $defaulyProperties[] = $data['name']; } $propertyValue = MemberProperty::find()->select(['_id', 'propertyId'])->from('memberProperty')->where(['isRequired' => true, 'isVisible' => true, 'isDefault' => false, 'isDeleted' => false, 'accountId' => new MongoId($args['accountId'])])->all(); foreach ($propertyValue as $data) { $properties[] = $data['propertyId']; } $propertyItems = array_merge($defaulyProperties, $properties); // get required properties in db. foreach ($propertyItems as $item) { if (array_key_exists($item, $dbExistProperties)) { $itemValue = $dbExistProperties[$item]; } else { $itemValue = $item; } if (!in_array(strtolower($itemValue), $title) && !in_array($itemValue, $requiredProperty)) { $requiredProperty[] = $itemValue; } } if (count($requiredProperty) > 0) { ResqueUtil::log(['error' => 'Resqued property is miss', 'args' => ['title' => $requiredProperty]]); $array = ['value' => null, 'rows' => null, 'cols' => null, 'property' => null, 'wrongNum' => self::MEMBER_NO_EXIST]; $this->storeError($redis, $array, $args); $redis->sadd($missPropertyKey, serialize($requiredProperty)); unset($requiredProperty); return false; } // check content for excel. $batchIndex = 1; $batchIndexColumn = []; $batch = 1; $batchs = ceil(($allRow - 1) / self::BATCH_COUNT); $decimal = $allRow % self::BATCH_COUNT; $result = []; $resultTitle = []; // Mapping between name and properties. $nameAndProperties = $defaulyProperty = MemberProperty::find()->select(['_id', 'name', 'propertyId'])->from('memberProperty')->where(['isDeleted' => false, 'accountId' => new MongoId($args['accountId'])])->all(); $mapProperties = []; if (!empty($nameAndProperties)) { foreach ($nameAndProperties as $item) { $mapProperties[] = $item->toArray(); } $result = ArrayHelper::map($mapProperties, 'propertyId', 'name'); $resultTitle = ArrayHelper::map($mapProperties, 'name', 'propertyId'); } // Get all tag $tags = Account::getAllTags(new MongoId($args['accountId'])); for ($rowIndex = 2; $rowIndex <= $allRow; $rowIndex++) { if ($batchIndex == self::BATCH_COUNT) { $batchIndex = 1; $batchIndexColumn = []; ++$batch; } $columnValue = []; $telName = ''; $telId = ''; $telValue = ''; $updateMember = []; $insertMember = []; $titleIndex = -1; for ($columnIndex = 'A'; $columnIndex <= $allColumn; $columnIndex++) { $titleIndex++; // get member propery by propertyId(the title of excel). //++$titleIndex; $columnNum = \PHPExcel_Cell::columnIndexFromString($columnIndex) - 1; $value = trim((string) $currentSheet->getCell($columnIndex . $rowIndex)->getValue()); $mobile = trim((string) $currentSheet->getCell($mobileColumn . $rowIndex)->getValue()); if ($titleIndex < count($title) && $columnNum == $titleIndex) { if (empty((string) $title[$titleIndex])) { continue; } // Verify if the mobile is right. if (empty($mobile)) { $array = ['value' => $mobile, 'rows' => $rowIndex, 'cols' => $mobileIndex + 1, 'property' => $title[$mobileIndex], 'wrongNum' => self::MEMBER_PROPERTY_REQUIRED]; $this->storeError($redis, $array, $args); return false; } else { if (strstr($mobile, self::MEMBER_ENGLISH_COLON)) { // check mobile.(T:1312797391); $str = explode(self::MEMBER_ENGLISH_COLON, $mobile); // T:1312797391 if ($str[0] != 'T') { $array = ['value' => $mobile, 'rows' => $rowIndex, 'cols' => $mobileIndex + 1, 'property' => $title[$mobileIndex], 'wrongNum' => self::MEMBER_PROPERTY_ERROR]; $this->storeError($redis, $array, $args); return false; } $telValue = $str[1]; } else { if (strstr($mobile, self::MEMBER_CHINESE_COLON)) { $str = explode(self::MEMBER_CHINESE_COLON, $mobile); if ($str[0] != 'T') { $array = ['value' => $mobile, 'rows' => $rowIndex, 'cols' => $mobileIndex + 1, 'property' => $title[$mobileIndex], 'wrongNum' => self::MEMBER_PROPERTY_ERROR]; $this->storeError($redis, $array, $args); return false; } $telValue = $str[1]; } else { $array = ['value' => $mobile, 'rows' => $rowIndex, 'cols' => $mobileIndex + 1, 'property' => $title[$mobileIndex], 'wrongNum' => self::MEMBER_PROPERTY_ERROR]; $this->storeError($redis, $array, $args); return false; } } if ((string) $title[$titleIndex] == self::MEMBER_MOBILE) { $value = (string) $telValue; } // get mobile in excel. if (!in_array((string) $telValue, $mobiles)) { $mobiles[] = (string) $telValue; } } // validate tag. if ($titles[$titleIndex] == self::MEMBER_TAGS) { if (!empty($value) && !in_array($value, $tags)) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } $columnValue[$rowIndex][] = ['tags' => $value]; } else { // get all the ignore properties. if (empty($property[$titleIndex])) { if (!in_array((string) $title[$titleIndex], $ignoreProperties)) { $ignoreProperties[] = (string) $title[$titleIndex]; } } else { if ($property[$titleIndex]['isVisible'] == false) { if (!in_array((string) $title[$titleIndex], $ignoreProperties)) { $ignoreProperties[] = (string) $title[$titleIndex]; } continue; } // Varitify if it`s required. if (strcasecmp($property[$titleIndex]['type'], self::MEMBER_RADIO) != 0 && (string) $title[$titleIndex] != self::MEMBER_MOBILE) { if ($property[$titleIndex]['isRequired'] == true && empty($value)) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_REQUIRED]; $this->storeError($redis, $array, $args); return false; } } // Varitify if it`s isUnique in excel. if (!empty($value) && $property[$titleIndex]['isUnique'] == true) { if ((string) $title[$titleIndex] != self::MEMBER_MOBILE) { // check db. $batchIndexColumn[$columnNum][] = $value; if ($decimal == 0 || $rowIndex == $allRow || $rowIndex == self::BATCH_COUNT) { // check update or insert, if the data will be insert, I will validate unique, not do it. $members = Member::findMobiles($mobiles, new MongoId($args['accountId'])); if (!empty($members)) { $memberId = []; foreach ($members as $member) { $mobile = ''; $uniqueFileValue = ''; $uniqueFileId = ''; foreach ($member['properties'] as $propertyItem) { if ($propertyItem['name'] == Member::DEFAULT_PROPERTIES_MOBILE) { $mobile = $propertyItem['value']; $index = array_search($mobile, $mobiles); unset($batchIndexColumn[$columnNum][$index]); } if ($propertyItem['id'] == $mapTitlePropertyId[$title[$titleIndex]]) { $uniqueFileValue = $propertyItem['value']; $uniqueFileId = $propertyItem['id']; } } $rindex = ($batch - 1) * self::BATCH_COUNT + $index + 2; $uniqueFileValue = trim((string) $currentSheet->getCell(\PHPExcel_Cell::stringFromColumnIndex($titleIndex) . $rindex)->getValue()); $isExisUpdatetProperties = Member::findOne(['properties' => ['$elemMatch' => ['id' => $uniqueFileId, 'value' => $uniqueFileValue]], '_id' => ['$ne' => $member['_id']], 'isDeleted' => false, 'accountId' => new MongoId($args['accountId'])]); if (!empty($isExisUpdatetProperties)) { if ($property[$titleIndex]['isDefault'] == true) { $array = ['value' => $value, 'rows' => $rindex, 'cols' => $titleIndex + 1, 'property' => $property[$titleIndex]['name'], 'wrongNum' => self::MEMBER_PROPERTY_UNIQUE]; $this->storeError($redis, $array, $args); return false; } else { $array = ['value' => $value, 'rows' => $rindex, 'cols' => $titleIndex + 1, 'property' => $property[$titleIndex]['propertyId'], 'wrongNum' => self::MEMBER_PROPERTY_UNIQUE]; $this->storeError($redis, $array, $args); return false; } } } } $isExistProperties = Member::findOne(['properties' => ['$elemMatch' => ['value' => ['$in' => $batchIndexColumn[$columnNum]], 'id' => $property[$titleIndex]['_id']]], 'isDeleted' => false, 'accountId' => new MongoId($args['accountId'])]); if (!empty($isExistProperties)) { foreach ($isExistProperties['properties'] as $propertyItem) { if ($property[$titleIndex]['_id'] == $propertyItem['id']) { if ($property[$titleIndex]['isDefault'] == true) { $colIndexNum = array_search(strtolower((string) $propertyItem['name']), $title) + 1; } else { $colIndexNum = array_search(strtolower($resultTitle[(string) $propertyItem['name']]), $title) + 1; } if ($rowIndex == 2) { $columnElements[$columnNum][] = ''; } if (in_array((string) $propertyItem['value'], $columnElements[$columnNum])) { $rowIndexNum = array_search((string) $propertyItem['value'], $columnElements[$columnNum]) + 2; } else { if ($rowIndex <= self::BATCH_COUNT) { $rowIndexNum = ($batch - 1) * self::BATCH_COUNT + count($batchIndexColumn[$columnNum]) + 1; } else { $rowIndexNum = ($batch - 1) * self::BATCH_COUNT + count($batchIndexColumn[$columnNum]); } } if ($rowIndex == 2) { unset($columnElements[$columnNum][0]); } } continue; } if ($property[$titleIndex]['isDefault'] == true) { $array = ['value' => $value, 'rows' => $rowIndexNum, 'cols' => $colIndexNum, 'property' => $property[$titleIndex]['name'], 'wrongNum' => self::MEMBER_PROPERTY_UNIQUE]; $this->storeError($redis, $array, $args); return false; } else { $array = ['value' => $value, 'rows' => $rowIndexNum, 'cols' => $colIndexNum, 'property' => $property[$titleIndex]['propertyId'], 'wrongNum' => self::MEMBER_PROPERTY_UNIQUE]; $this->storeError($redis, $array, $args); return false; } } } // check excel. $isInsert = $redis->Hset($cacheHash . $columnNum, $value, $columnNum); if ($isInsert == 0) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_UNIQUE]; $this->storeError($redis, $array, $args); return false; } } $columnElements[$columnNum][] = $value; } switch ($property[$titleIndex]['type']) { case Member::DEFAULT_PROPERTIES_EMAIL: $EmailTitle = $title[$titleIndex]; $EmailTitles = $titles[$titleIndex]; $EmailParams = ['redis' => $redis, 'args' => $args, 'titleIndex' => $titleIndex, 'EmailTitles' => $EmailTitles]; $EmailTitleIndex = $titleIndex + 1; $propertyError = self::MEMBER_PROPERTY_ERROR; $Emailarray = ['value' => $value, 'rows' => $rowIndex, 'cols' => $EmailTitleIndex, 'property' => $EmailTitle, 'wrongNum' => $propertyError]; $columnValue[$rowIndex][] = $this->validateEmail($Emailarray, $EmailParams, $property, $result, $realTitles, $titles); break; case self::MEMBER_DATE: if (!empty($value)) { if (strstr($value, '-')) { $str = explode('-', $value); if (count($str) != 3) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ERROR]; $this->storeError($redis, $array, $args); return false; } } if (strstr($value, self::MEMBER_LINE)) { $str = explode(self::MEMBER_LINE, $value); if (count($str) == 3) { $time = $str[2] . '-' . $str[0] . '-' . $str[1]; } else { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ERROR]; $this->storeError($redis, $array, $args); return false; } } else { $time = $value; } } if (!empty($value) && !preg_match($reDateOne, $time)) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } if (!empty($value)) { if (strstr($value, self::MEMBER_LINE)) { $str = explode(self::MEMBER_LINE, $value); $dayStr = $str[2] . '-' . $str[0] . '-' . $str[1]; $date = (int) strtotime($dayStr) * 1000; } else { $date = (int) strtotime($value) * 1000; } } else { $date = null; } if (!empty($value) && $date >= time() * 1000) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => $date]; break; case self::MEMBER_CHECKBOX: $checkboxValue = []; if (!empty($value) && strstr($value, self::MEMBER_ENGLISH_COMMA) && !strstr($value, self::MEMBER_CHINESE_COMMA)) { //english $checkboxValue = explode(self::MEMBER_ENGLISH_COMMA, $value); $checkboxValue = array_values(array_unique($checkboxValue)); } if (!empty($value) && strstr($value, self::MEMBER_CHINESE_COMMA) && !strstr($value, self::MEMBER_ENGLISH_COMMA)) { // chinese $checkboxValue = explode(self::MEMBER_CHINESE_COMMA, $value); $checkboxValue = array_values(array_unique($checkboxValue)); } if (!empty($value) && strstr($value, self::MEMBER_ENGLISH_COMMA) && strstr($value, self::MEMBER_CHINESE_COMMA)) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ERROR]; $this->storeError($redis, $array, $args); return false; } // one value if (!empty($value) && !strstr($value, self::MEMBER_ENGLISH_COMMA) && !strstr($value, self::MEMBER_CHINESE_COMMA)) { $checkboxValue[] = $value; } if (count($checkboxValue) > 0) { foreach ($checkboxValue as $item) { if (!in_array($item, $property[$titleIndex]['options'])) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } continue; } } $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => $checkboxValue]; break; case self::MEMBER_RADIO: if ((string) $title[$titleIndex] != Member::DEFAULT_PROPERTIES_GENDER) { if (!empty($value) && !in_array($value, $property[$titleIndex]['options'])) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => empty($value) ? $property[$titleIndex]['options'][0] : $value]; } else { if (!empty($value) && $value == self::MEMBER_SC_GENDER || $value == self::MEMBER_TC_GENDER || strcasecmp($value, self::MEMBER_MALE) == 0) { $genderValue = self::MEMBER_MALE; } else { if (!empty($value) && $value == self::MEMBER_C_GENDER || strcasecmp($value, self::MEMBER_FEMALE) == 0) { $genderValue = self::MEMBER_FEMALE; } else { if (!empty($value) && $value == self::MEMBER_WEIZHI || $value == self::MEMBER_UNKNOW || strcasecmp($value, self::MEMBER_UNKNOWN) == 0) { $genderValue = self::MEMBER_UNKNOWN; } else { if (empty($value)) { $genderValue = self::MEMBER_MALE; } else { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } } } } $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => $genderValue]; } break; case MemberProperty::TYPE_TEXTAREA: $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => str_replace("\\n", PHP_EOL, $value)]; break; default: if ((string) $title[$titleIndex] == Member::DEFAULT_PROPERTIES_NAME) { $valueLen = mb_strlen($value, 'utf-8'); if (!empty($value)) { if ($valueLen < 2 || $valueLen > 30) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } } $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => $value]; } else { switch ((string) $title[$titleIndex]) { case self::MEMBER_MOBILE: if (!empty($value) && !preg_match($re, $value) && !preg_match($reTel, $value)) { $array = ['value' => $value, 'rows' => $rowIndex, 'cols' => $titleIndex + 1, 'property' => $title[$titleIndex], 'wrongNum' => self::MEMBER_PROPERTY_ILLEGAL]; $this->storeError($redis, $array, $args); return false; } $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => $value]; $telName = $defaultProperties[(string) $title[$titleIndex]]; $telId = (string) $property[$titleIndex]['_id']; $telValue = $value; break; default: $columnValue[$rowIndex][] = ['id' => $property[$titleIndex]['_id'], 'name' => $property[$titleIndex]['isDefault'] == true ? $titles[$titleIndex] : $result[$realTitles[$titleIndex]], 'value' => $value]; break; } } break; } } } } } // verify if the column value has already exist. if it is exist, will store $updateMember, // if it isn`s exist, will store $insertMember. $total++; $memberOne = null; if (!empty($telId)) { $memberOne = Member::findOne(['properties' => ['$elemMatch' => ['id' => new MongoId($telId), 'name' => $telName, 'value' => $telValue]], 'accountId' => new MongoId($args['accountId'])]); } if (!empty($memberOne)) { $updateMember[] = $columnValue[$rowIndex]; $redis->sadd($cacheSetUpdate, serialize($updateMember)); } else { if (!empty($columnValue[$rowIndex])) { $insertMember[] = $columnValue[$rowIndex]; $redis->sadd($cacheSetInsert, serialize($insertMember)); } } ++$batchIndex; } unset($columnElements); $redis->del($cacheHash . $columnNum); //store the number of the wrong code and the number of the right code $rightInsert = $redis->scard($cacheSetInsert); $rightUpdate = $redis->scard($cacheSetUpdate); $right = $rightInsert + $rightUpdate; $wrong = $total - $right; $redis->Hset($cacheHash, $wrongKey, $wrong); $redis->Hset($cacheHash, $rightKey, $right); // store the ignore of properties. if ($wrong == 0 && count($ignoreProperties) > 0) { $redis->sadd($ignorePropertyKey, serialize($ignoreProperties)); } else { $redis->sadd($ignorePropertyKey, null); } return true; }