├── assets └── snippets │ └── FormLister │ ├── __autoload.php │ ├── config │ └── core │ │ └── default.json │ ├── core │ ├── FormLister.abstract.php │ ├── controller │ │ ├── Activate.php │ │ ├── Content.php │ │ ├── DeleteContent.php │ │ ├── DeleteUser.php │ │ ├── Form.php │ │ ├── Login.php │ │ ├── MailChimp.php │ │ ├── Profile.php │ │ ├── Register.php │ │ └── Reminder.php │ └── lang │ │ ├── de │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ ├── en │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ ├── es │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ ├── it │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ ├── nl │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ ├── pl │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ ├── ru │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ │ └── uk │ │ ├── activate.inc.php │ │ ├── content.inc.php │ │ ├── csrf.inc.php │ │ ├── deleteContent.inc.php │ │ ├── deleteUser.inc.php │ │ ├── form.inc.php │ │ ├── login.inc.php │ │ ├── mailchimp.inc.php │ │ ├── profile.inc.php │ │ ├── register.inc.php │ │ └── reminder.inc.php │ ├── docs │ └── history.md │ ├── lib │ ├── DateConverter.php │ ├── Debug.php │ ├── FileValidator.php │ ├── Filters.php │ ├── Gpc.php │ ├── Lexicon.php │ ├── MailChimp │ │ ├── Batch.php │ │ └── MailChimp.php │ ├── SubmitProtection.php │ ├── Validator.php │ └── captcha │ │ ├── Captcha.php │ │ ├── modxCaptcha │ │ ├── connector.php │ │ ├── modxCaptcha.php │ │ ├── noises │ │ │ ├── index.html │ │ │ ├── noise1.jpg │ │ │ ├── noise2.jpg │ │ │ ├── noise3.jpg │ │ │ └── noise4.jpg │ │ ├── ttf │ │ │ └── ftb_____.ttf │ │ └── wrapper.php │ │ ├── reCaptcha │ │ └── wrapper.php │ │ ├── smsCaptcha │ │ ├── model.php │ │ └── wrapper.php │ │ └── yandexCaptcha │ │ └── wrapper.php │ ├── plugin.userHelper.php │ └── snippet.FormLister.php └── install └── assets ├── plugins └── userHelper.tpl └── snippets └── FormLister.tpl /assets/snippets/FormLister/__autoload.php: -------------------------------------------------------------------------------- 1 | '/../../lib/APIHelpers.class.php', 9 | 'AssetsHelper' => '/../../lib/Helpers/Assets.php', 10 | 'DLTemplate' => '/../DocLister/lib/DLTemplate.class.php', 11 | 'DLphx' => '/../DocLister/lib/DLphx.class.php', 12 | 'DrewM\\MailChimp\\Batch' => '/lib/MailChimp/Batch.php', 13 | 'DrewM\\MailChimp\\MailChimp' => '/lib/MailChimp/MailChimp.php', 14 | 'FormLister\\Activate' => '/core/controller/Activate.php', 15 | 'FormLister\\CaptchaInterface' => '/lib/captcha/Captcha.php', 16 | 'FormLister\\Content' => '/core/controller/Content.php', 17 | 'FormLister\\Core' => '/core/FormLister.abstract.php', 18 | 'FormLister\\DateConverter' => '/lib/DateConverter.php', 19 | 'FormLister\\DeleteContent' => '/core/controller/DeleteContent.php', 20 | 'FormLister\\DeleteUser' => '/core/controller/DeleteUser.php', 21 | 'FormLister\\FileValidator' => '/lib/FileValidator.php', 22 | 'FormLister\\Filters' => '/lib/Filters.php', 23 | 'FormLister\\Form' => '/core/controller/Form.php', 24 | 'FormLister\\Login' => '/core/controller/Login.php', 25 | 'FormLister\\MailChimp' => '/core/controller/MailChimp.php', 26 | 'FormLister\\Profile' => '/core/controller/Profile.php', 27 | 'FormLister\\Register' => '/core/controller/Register.php', 28 | 'FormLister\\Reminder' => '/core/controller/Reminder.php', 29 | 'FormLister\\SubmitProtection' => '/lib/SubmitProtection.php', 30 | 'FormLister\\Validator' => '/lib/Validator.php', 31 | 'Formatter\\HtmlFormatter' => '/../../lib/Formatter/HtmlFormatter.php', 32 | 'Formatter\\SqlFormatter' => '/../../lib/Formatter/SqlFormatter.php', 33 | 'Helpers\\Collection' => '/../../lib/Helpers/Collection.php', 34 | 'Helpers\\Config' => '/../../lib/Helpers/Config.php', 35 | 'Helpers\\Debug' => '/lib/Debug.php', 36 | 'Helpers\\FS' => '/../../lib/Helpers/FS.php', 37 | 'Helpers\\Gpc' => '/lib/Gpc.php', 38 | 'Helpers\\Lexicon' => '/../../lib/Helpers/Lexicon.php', 39 | 'Helpers\\Lexicon\\AbstractLexiconHandler' => '/../../lib/Helpers/LexiconHandlers/AbstractLexiconHandler.php', 40 | 'Helpers\\Lexicon\\EvoBabelLexiconHandler' => '/../../lib/Helpers/LexiconHandlers/EvoBabelLexiconHandler.php', 41 | 'Helpers\\Mailer' => '/../../lib/Helpers/Mailer.php', 42 | 'Helpers\\PHPThumb' => '/../../lib/Helpers/PHPThumb.php', 43 | 'Helpers\\Video' => '/../../lib/Helpers/Video.php', 44 | 'MODxAPI' => '/../../lib/MODxAPI/MODx.php', 45 | 'MODxAPIhelpers' => '/../../lib/MODxAPI/MODx.php', 46 | 'ModxCaptcha' => '/lib/captcha/modxCaptcha/modxCaptcha.php', 47 | 'ModxCaptchaWrapper' => '/lib/captcha/modxCaptcha/wrapper.php', 48 | 'ReCaptchaWrapper' => '/lib/captcha/reCaptcha/wrapper.php', 49 | 'SmsCaptchaWrapper' => '/lib/captcha/smsCaptcha/wrapper.php', 50 | 'SmsModel' => '/lib/captcha/smsCaptcha/model.php', 51 | 'SummaryText' => '/../../lib/class.summary.php', 52 | 'autoTable' => '/../../lib/MODxAPI/autoTable.abstract.php', 53 | 'jsonHelper' => '/../DocLister/lib/jsonHelper.class.php', 54 | 'modCategories' => '/../../lib/MODxAPI/modCategories.php', 55 | 'modChunk' => '/../../lib/MODxAPI/modChunk.php', 56 | 'modModule' => '/../../lib/MODxAPI/modModule.php', 57 | 'modPlugin' => '/../../lib/MODxAPI/modPlugin.php', 58 | 'modResource' => '/../../lib/MODxAPI/modResource.php', 59 | 'modSnippet' => '/../../lib/MODxAPI/modSnippet.php', 60 | 'modTV' => '/../../lib/MODxAPI/modTV.php', 61 | 'modTemplate' => '/../../lib/MODxAPI/modTemplate.php', 62 | 'modUsers' => '/../../lib/MODxAPI/modUsers.php', 63 | 'sqlHelper' => '/../DocLister/lib/sqlHelper.class.php', 64 | 'xNop' => '/../DocLister/lib/xnop.class.php' 65 | ); 66 | } 67 | if (isset($classes[$class])) { 68 | require dirname(__FILE__) . $classes[$class]; 69 | } 70 | }; 71 | spl_autoload_register($loader, true); 72 | // @codeCoverageIgnoreEnd 73 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/config/core/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorClass":" has-error", 3 | "requiredClass":" has-warning", 4 | "subject":"Новое сообщение", 5 | "messagesOuterTpl":"@CODE:
[+messages+]
", 6 | "errorTpl":"@CODE:[+message+]" 7 | } -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Activate.php: -------------------------------------------------------------------------------- 1 | user = $this->loadModel( 37 | $this->getCFGDef('model', '\modUsers'), 38 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 39 | ); 40 | $this->lexicon->fromFile('activate'); 41 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 42 | $userField = $this->getCFGDef('userField', 'email'); 43 | $this->userField = $userField; 44 | $uidName = $this->getCFGDef('uidName', $this->user->fieldPKName()); 45 | if (!isset($_REQUEST['formid']) && !isset($_REQUEST[$userField]) && (isset($_REQUEST['hash']) && !empty($_REQUEST['hash']) && isset($_REQUEST[$uidName]) && !empty($_REQUEST[$uidName]))) { 46 | $this->setField('hash', $_REQUEST['hash']); 47 | $this->setField('id', (int)$_REQUEST[$uidName]); 48 | $this->mode = 'activate'; 49 | } 50 | $this->log('Activate mode is ' . $this->mode); 51 | } 52 | 53 | /** 54 | * @return string 55 | */ 56 | public function render() 57 | { 58 | if ($id = (int)$this->modx->getLoginUserID('web')) { 59 | $this->redirect('exitTo'); 60 | $this->user->edit($id); 61 | $this->setFields($this->user->toArray()); 62 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->translate('activate.default_skipTpl')); 63 | $this->setValid(false); 64 | } 65 | 66 | if ($this->mode == 'activate') { 67 | $this->renderActivate(); 68 | } 69 | 70 | return parent::render(); 71 | } 72 | 73 | /** 74 | * 75 | */ 76 | public function renderActivate() 77 | { 78 | $hash = $this->getField('hash'); 79 | $uid = (int)$this->getField('id'); 80 | if (is_scalar($hash) && $hash && $hash == $this->getUserHash($uid)) { 81 | $this->process(); 82 | } else { 83 | $this->addMessage($this->translate('activate.update_failed')); 84 | $this->setValid(false); 85 | } 86 | 87 | return; 88 | } 89 | 90 | /** 91 | * @param $uid 92 | * @return bool|string 93 | */ 94 | public function getUserHash($uid) 95 | { 96 | if (is_null($this->user)) { 97 | $hash = false; 98 | } else { 99 | $userdata = $this->user->edit($uid)->toArray(); 100 | $hash = $this->user->getID() && !$userdata['verified'] ? md5(jsonHelper::toJson($userdata)) : false; 101 | } 102 | 103 | return $hash; 104 | } 105 | 106 | /** 107 | * 108 | */ 109 | public function process() 110 | { 111 | switch ($this->mode) { 112 | /** 113 | * Задаем хэш, отправляем пользователю ссылку для активации 114 | */ 115 | case "hash": 116 | $uid = $this->getField($this->userField); 117 | $password = $this->getField('password'); 118 | if ($hash = $this->getUserHash($uid)){ 119 | $this->setFields($this->user->toArray()); 120 | $url = $this->getCFGDef('activateTo', isset($this->modx->documentIdentifier) && $this->modx->documentIdentifier > 0 ? $this->modx->documentIdentifier : $this->modx->getConfig('site_start')); 121 | $uidName = $this->getCFGDef('uidName', $this->user->fieldPKName()); 122 | $query = http_build_query([$uidName => $this->getField($this->userField), 'hash' => $hash]); 123 | if(is_numeric($url)) { 124 | $url = $this->modx->makeUrl($url, "", $query, 'full'); 125 | } else { 126 | $url .= '?' . $query; 127 | } 128 | $this->setField('activate.url', $url); 129 | $this->mailConfig['to'] = $this->user->get('email'); 130 | parent::process(); 131 | } else { 132 | $this->addMessage($this->translate('activate.no_activation')); 133 | } 134 | break; 135 | /** 136 | * Отправляем пользователю письмо для активации, если указан шаблон такого письма 137 | */ 138 | case "activate": 139 | $uid = (int)$this->getField('id'); 140 | $hash = $this->getField('hash'); 141 | if ($hash && $hash == $this->getUserHash($uid)) { 142 | $result = $this->user->edit($uid)->set('verified', 1)->save(true); 143 | $this->log('Activate user', ['user' => $uid, 'result' => $result]); 144 | if (!$result) { 145 | $this->addMessage($this->translate('activate.update_failed')); 146 | } else { 147 | $this->setFields($this->user->toArray()); 148 | if ($tpl = $this->getCFGDef('activateReportTpl')) { 149 | $this->mailConfig['to'] = $this->getField('email'); 150 | $this->config->setConfig([ 151 | 'reportTpl' => $tpl 152 | ]); 153 | parent::process(); 154 | } 155 | } 156 | } else { 157 | $this->addMessage($this->translate('activate.update_failed')); 158 | } 159 | break; 160 | } 161 | } 162 | 163 | /** 164 | * @return string 165 | */ 166 | public function getMode() { 167 | return $this->mode; 168 | } 169 | 170 | /** 171 | * 172 | */ 173 | public function postProcess() 174 | { 175 | $this->setFormStatus(true); 176 | $this->runPrepare('prepareAfterProcess'); 177 | switch ($this->mode) { 178 | case 'hash': 179 | $tpl = $this->getCFGDef('successTpl', 180 | $this->translate('activate.default_successTpl')); 181 | break; 182 | case 'activate': 183 | $this->redirect(); 184 | $tpl = $this->getCFGDef('activateSuccessTpl', 185 | $this->translate('activate.default_activateSuccessTpl')); 186 | } 187 | if (!empty($tpl)) { 188 | $this->renderTpl = $tpl; 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Content.php: -------------------------------------------------------------------------------- 1 | lexicon->fromFile('content'); 44 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 45 | $this->content = $this->loadModel( 46 | $this->getCFGDef('model', '\modResource'), 47 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modResource.php') 48 | ); 49 | if (is_null($this->content)) { 50 | return; 51 | } 52 | $this->user = $this->loadModel( 53 | $this->getCFGDef('userModel', '\modUsers'), 54 | $this->getCFGDef('userModelPath', 'assets/lib/MODxAPI/modUsers.php') 55 | ); 56 | $idField = $this->getCFGDef('idField', 'id'); 57 | $id = $this->getCFGDef($idField); 58 | if ($idField) { 59 | if ($id) { 60 | $this->mode = 'edit'; 61 | $this->id = $id; 62 | } elseif (isset($_REQUEST[$idField]) && is_scalar($_REQUEST[$idField]) && (int)$_REQUEST[$idField] > 0) { 63 | $this->id = (int)$_REQUEST[$idField]; 64 | $this->mode = 'edit'; 65 | } 66 | } 67 | $data = []; 68 | if ($this->mode == 'edit') { 69 | $data = $this->content->edit($this->id)->toArray('', '', '_', false); 70 | $this->mailConfig['noemail'] = 1; 71 | if ($ds = $this->getCFGDef('defaultsSources')) { 72 | $defaultsSources = "{$ds};param:contentdata"; 73 | } else { 74 | $defaultsSources = "param:contentdata"; 75 | } 76 | $this->config->setConfig([ 77 | 'defaultsSources' => $defaultsSources, 78 | 'contentdata' => $data, 79 | 'formTpl' => $this->getCFGDef('editTpl', $this->getCFGDef('formTpl')), 80 | 'successTpl' => $this->getCFGDef('editSuccessTpl'), 81 | 'onlyUsers' => 1, 82 | 'protectSubmit' => 0, 83 | 'submitLimit' => 0 84 | ]); 85 | } 86 | $this->log('Content mode is ' . $this->mode, ['data' => $data]); 87 | } 88 | 89 | /** 90 | * @return string 91 | */ 92 | public function render() 93 | { 94 | $uid = (int)$this->modx->getLoginUserID('web'); 95 | $ownerField = $this->getCFGDef('ownerField', 'aid'); 96 | $mode = $this->mode; 97 | $flag = true; 98 | 99 | if ($mode == 'create') { 100 | if ($this->getCFGDef('onlyUsers', 1)) { 101 | if (!$uid) { 102 | $this->redirect('exitTo'); 103 | $this->renderTpl = $this->getCFGDef('skipTpl', 104 | $this->translate('create.default_skipTpl')); 105 | $flag = false; 106 | } elseif (!$this->checkUserGroups($uid, $this->getCFGDef('userGroups'))) { 107 | $this->redirect('badGroupTo'); 108 | $this->renderTpl = $this->getCFGDef('badGroupTpl', 109 | $this->translate('create.default_badGroupTpl')); 110 | $flag = false; 111 | } 112 | } 113 | $this->owner = $uid; 114 | } 115 | 116 | if ($mode == 'edit') { 117 | if (!$uid) { 118 | $this->redirect('exitTo'); 119 | $this->renderTpl = $this->getCFGDef('skipEditTpl', 120 | $this->translate('edit.default_skipEditTpl')); 121 | $flag = false; 122 | } elseif (!$this->checkUserGroups($uid, $this->getCFGDef('userGroups'))) { 123 | $this->redirect('badGroupTo'); 124 | $this->renderTpl = $this->getCFGDef('badGroupTpl', 125 | $this->translate('edit.default_badGroupTpl')); 126 | $flag = false; 127 | } else { 128 | $cid = is_null($this->content) ? false : $this->content->getID(); 129 | if ($cid) { 130 | $owner = (int)$this->content->get($ownerField); 131 | if ($this->getCFGDef('onlyOwners', 1) && $owner !== $uid) { 132 | $this->redirect('badOwnerTo'); 133 | $this->renderTpl = $this->getCFGDef('badOwnerTpl', 134 | $this->translate('edit.default_badOwnerTpl')); 135 | $flag = false; 136 | } 137 | $this->owner = $uid; 138 | } else { 139 | $this->redirect('badRecordTo'); 140 | $this->renderTpl = $this->getCFGDef('badRecordTpl', 141 | $this->translate('edit.default_badRecordTpl')); 142 | $flag = false; 143 | } 144 | } 145 | 146 | if ($flag && !$this->isSubmitted()) { 147 | $fields = $this->getContentFields(); 148 | $this->setFields($fields); 149 | } 150 | } 151 | 152 | $this->setValid($flag); 153 | 154 | return parent::render(); 155 | } 156 | 157 | /** 158 | * 159 | */ 160 | public function process() 161 | { 162 | $fields = $this->getContentFields(); 163 | $ownerField = $this->getCFGDef('ownerField', 'aid'); 164 | $result = false; 165 | if ($fields && !is_null($this->content)) { 166 | $clearCache = $this->getCFGDef('clearCache', false); 167 | switch ($this->mode) { 168 | case 'create': 169 | if ($this->checkSubmitProtection() || $this->checkSubmitLimit()) { 170 | return; 171 | } 172 | if ($this->owner || !$this->getCFGDef('onlyUsers', 1)) { 173 | $fields[$ownerField] = $this->owner; 174 | $result = $this->content->create($fields)->save(true, $clearCache); 175 | $this->log('Create record', ['data' => $fields, 'result' => $result ,'log' => $this->content->getLog()]); 176 | } 177 | if ($result) { 178 | $url = ''; 179 | 180 | $evtOut = $this->modx->invokeEvent('OnMakeDocUrl', [ 181 | 'invokedBy' => __CLASS__, 182 | 'id' => $result, 183 | 'data' => $this->getFormData('fields') 184 | ]); 185 | if (is_array($evtOut) && count($evtOut) > 0) { 186 | $url = array_pop($evtOut); 187 | } 188 | if ($url) { 189 | $this->setField('content.url', $url); 190 | } 191 | $this->log('Created record', ['data' => $fields, 'result' => $result]); 192 | } 193 | break; 194 | case 'edit': 195 | $result = $this->content->fromArray($fields)->save(true, $clearCache); 196 | if ($result) { 197 | $this->log('Update record', ['data' => $fields, 'result' => $result]); 198 | } 199 | break; 200 | } 201 | } 202 | if (!$result) { 203 | $this->log('Save failed', ['model' => get_class($this->content), 'data' => $fields]); 204 | $this->addMessage($this->translate('edit.update_failed')); 205 | } else { 206 | $this->content->close(); 207 | $this->setFields($this->content->edit($result)->toArray('', '', '_', false)); 208 | if ($this->getCFGDef('contentFields')) { 209 | $this->setFields($this->getContentFields(true)); 210 | } 211 | if ($this->owner) { 212 | $this->setFields($this->user->edit($this->owner)->toArray(), 'user'); 213 | } 214 | $this->runPrepare('preparePostProcess'); 215 | $this->log('Update form data', ['data' => $this->getFormData('fields')]); 216 | if ($this->mode == 'create') { 217 | parent::process(); 218 | } else { 219 | $this->postProcess(); 220 | } 221 | } 222 | } 223 | 224 | /** 225 | * 226 | */ 227 | public function postProcess() 228 | { 229 | $this->setFormStatus(true); 230 | $this->runPrepare('prepareAfterProcess'); 231 | if ($this->mode == 'create') { 232 | if ($this->getCFGDef('editAfterCreate', 0)) { 233 | $idField = $this->getCFGDef('idField'); 234 | $this->redirect('redirectTo', [$idField => $this->getField($idField)]); 235 | } else { 236 | $this->redirect(); 237 | } 238 | $this->renderTpl = $this->getCFGDef('successTpl', $this->translate('create.default_successTpl')); 239 | } else { 240 | if ($successTpl = $this->getCFGDef('successTpl')) { 241 | $this->renderTpl = $successTpl; 242 | } else { 243 | $this->addMessage($this->translate('edit.update_success')); 244 | } 245 | } 246 | } 247 | 248 | /** 249 | * @param bool $flip 250 | * @return array 251 | */ 252 | public function getContentFields($flip = false) 253 | { 254 | $fields = []; 255 | $contentFields = $this->getCFGDef('contentFields'); 256 | $contentFields = $this->config->loadArray($contentFields, ''); 257 | if (!$contentFields) { 258 | $fields = $this->filterFields($this->getFormData('fields'), $this->allowedFields, $this->forbiddenFields); 259 | $this->log('Unable to get juxtaposition of content fields', ['contentFields' => $fields]); 260 | } else { 261 | if ($flip || ($this->mode == 'edit' && !$this->isSubmitted())) { 262 | $contentFields = array_flip($contentFields); 263 | } 264 | foreach ($contentFields as $field => $formField) { 265 | $formField = $this->getField($formField); 266 | if ($formField !== '' || $this->getCFGDef('allowEmptyFields', 1)) { 267 | $fields[$field] = $formField; 268 | } 269 | } 270 | $this->log('Juxtaposition of content fields', ['contentFields' => $fields]); 271 | } 272 | 273 | return $fields; 274 | } 275 | 276 | /** 277 | * @return string 278 | */ 279 | public function getMode() 280 | { 281 | return $this->mode; 282 | } 283 | 284 | /** 285 | * @param $uid 286 | * @param string $groups 287 | * @return bool 288 | */ 289 | public function checkUserGroups($uid, $groups = '') 290 | { 291 | $flag = true; 292 | if (is_scalar($groups) && !empty($groups) && !is_null($this->user)) { 293 | $groups = explode(';', $groups); 294 | if (!empty($groups)) { 295 | $userGroups = $this->user->getUserGroups($uid); 296 | $flag = !empty(array_intersect($groups, $userGroups)); 297 | } 298 | } 299 | $this->log('Check user groups', ['result' => $flag]); 300 | 301 | return $flag; 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/DeleteContent.php: -------------------------------------------------------------------------------- 1 | content = $this->loadModel( 35 | $this->getCFGDef('model', '\modResource'), 36 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modResource.php') 37 | ); 38 | $this->user = $this->loadModel( 39 | $this->getCFGDef('model', '\modUsers'), 40 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 41 | ); 42 | $this->lexicon->fromFile('deleteContent'); 43 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 44 | $idField = $this->getCFGDef('idField','id'); 45 | if (isset($_REQUEST[$idField]) && is_scalar($_REQUEST[$idField])) { 46 | $this->id = (int)$_REQUEST[$idField]; 47 | } 48 | $this->config->setConfig([ 49 | 'ignoreMailerResult' => 1, 50 | 'protectSubmit' => 0, 51 | 'submitLimit' => 0 52 | ]); 53 | } 54 | 55 | /** 56 | * @return string 57 | */ 58 | public function render() 59 | { 60 | $flag = false; 61 | $uid = $this->modx->getLoginUserID('web'); 62 | if (!$uid) { 63 | $this->redirect('exitTo'); 64 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->translate('deleteContent.default_skipTpl')); 65 | } elseif (!$this->id || !$this->content->edit($this->id)->getID() || $this->content->get('deleted')) { 66 | $this->redirect('badRecordTo'); 67 | $this->renderTpl = $this->getCFGDef('badRecordTpl', 68 | $this->translate('deleteContent.default_badRecordTpl')); 69 | } elseif ($uid != $this->content->edit($this->id)->get($this->getCFGDef('ownerField','aid'))) { 70 | $this->renderTpl = $this->getCFGDef('badOwnerTpl', 71 | $this->translate('deleteContent.default_badOwnerTpl')); 72 | } else { 73 | $flag = true; 74 | $this->setFields($this->content->edit($this->id)->toArray()); 75 | $this->setFields($this->user->edit($uid)->toArray(),'user'); 76 | }; 77 | $this->setValid($flag); 78 | 79 | return parent::render(); 80 | } 81 | 82 | 83 | /** 84 | * 85 | * @throws \Exception 86 | */ 87 | public function process() 88 | { 89 | $result = $this->content->delete($this->id, true); 90 | if ($result) { 91 | return parent::process(); 92 | } else { 93 | return $this->addMessage($this->translate('deleteContent.delete_failed')); 94 | } 95 | } 96 | 97 | public function postProcess() 98 | { 99 | parent::postProcess(); 100 | $this->renderTpl = $this->getCFGDef('successTpl', $this->translate('deleteContent.default_successTpl')); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/DeleteUser.php: -------------------------------------------------------------------------------- 1 | lexicon->fromFile('deleteUser'); 26 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 27 | $uid = $modx->getLoginUserId('web'); 28 | $userdata = []; 29 | if ($uid) { 30 | $this->user = $this->loadModel( 31 | $this->getCFGDef('model', '\modUsers'), 32 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 33 | ); 34 | if (!is_null($this->user)) { 35 | $userdata = $this->user->edit($uid)->toArray(); 36 | unset($userdata['password']); 37 | } 38 | $this->config->setConfig([ 39 | 'ignoreMailerResult' => 1, 40 | 'keepDefaults' => 1, 41 | 'protectSubmit' => 0, 42 | 'submitLimit' => 0, 43 | 'userdata' => $userdata 44 | ]); 45 | } 46 | } 47 | 48 | /** 49 | * Загружает в formData данные не из формы 50 | * @param string $sources список источников 51 | * @param string $arrayParam название параметра с данными 52 | * @return $this 53 | */ 54 | public function setExternalFields ($sources = 'array', $arrayParam = 'defaults') 55 | { 56 | parent::setExternalFields($sources, $arrayParam); 57 | parent::setExternalFields('array', 'userdata'); 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * @return string 64 | */ 65 | public function render() 66 | { 67 | if (!$this->modx->getLoginUserID('web')) { 68 | $this->redirect('exitTo'); 69 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->translate('deleteUser.default_skipTpl')); 70 | $this->setValid(false); 71 | }; 72 | 73 | return parent::render(); 74 | } 75 | 76 | 77 | /** 78 | * 79 | */ 80 | public function process() 81 | { 82 | $uid = (int)$this->modx->getLoginUserID('web'); 83 | if (!is_null($this->user)) { 84 | $password = $this->getField('password'); 85 | if ($this->user->testAuth($uid, $password, true)) { 86 | $result = $this->user->delete($uid, true); 87 | if ($result) { 88 | $this->user->logout(); 89 | parent::process(); 90 | } else { 91 | return $this->addMessage($this->translate('deleteUser.delete_failed')); 92 | } 93 | } 94 | } 95 | 96 | return $this->addMessage($this->translate('deleteUser.delete_failed')); 97 | } 98 | 99 | /** 100 | * 101 | */ 102 | public function postProcess() 103 | { 104 | parent::postProcess(); 105 | $this->renderTpl = $this->getCFGDef('successTpl', $this->translate('deleteUser.default_successTpl')); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Form.php: -------------------------------------------------------------------------------- 1 | mailConfig = [ 32 | 'isHtml' => $this->getCFGDef('isHtml', 1), 33 | 'to' => $this->getCFGDef('to', ''), 34 | 'from' => $this->getCFGDef('from', $this->modx->getConfig('emailsender')), 35 | 'fromName' => $this->getCFGDef('fromName', $this->modx->getConfig('site_name')), 36 | 'subject' => $this->getCFGDef('subject', ''), 37 | 'replyTo' => $this->getCFGDef('replyTo', ''), 38 | 'cc' => $this->getCFGDef('cc', ''), 39 | 'bcc' => $this->getCFGDef('bcc', ''), 40 | 'noemail' => $this->getCFGDef('noemail', false) 41 | ]; 42 | $this->lexicon->fromFile('form'); 43 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 44 | } 45 | 46 | /** 47 | * Формирует текст письма для отправки 48 | * Если основной шаблон письма не задан, то формирует список полей формы 49 | * @param string $tplParam имя параметра с шаблоном письма 50 | * @return null|string 51 | */ 52 | public function renderReport ($tplParam = 'reportTpl') 53 | { 54 | $tpl = $this->getCFGDef($tplParam, ''); 55 | $skipPrerender = $this->getCFGDef('skipPrerender', 0); 56 | if (empty($tpl) && $tplParam == 'reportTpl') { 57 | $tpl = '@CODE:'; 58 | foreach ($this->getFormData('fields') as $key => $value) { 59 | $tpl .= \APIhelpers::e($key) . ": [+{$key}.value+]" . PHP_EOL; 60 | } 61 | $skipPrerender = false; 62 | } 63 | $out = $this->parseChunk($tpl, $skipPrerender ? $this->getFormData('fields') : $this->prerenderForm(true)); 64 | 65 | return $out; 66 | } 67 | 68 | /** 69 | * Получает тему письма из шаблона или строки 70 | * @param string $param 71 | * @return mixed|null|string 72 | */ 73 | public function renderSubject ($param = 'subject') 74 | { 75 | $subject = $this->getCFGDef($param . 'Tpl'); 76 | if (!empty($subject)) { 77 | $subject = $this->parseChunk($subject, $this->prerenderForm(true)); 78 | } else { 79 | $subject = $this->getCFGDef($param, ''); 80 | } 81 | if($param !== 'subject' && empty($subject)) { 82 | $subject = $this->renderSubject(); 83 | } 84 | 85 | return $subject; 86 | } 87 | 88 | /** 89 | * @return array 90 | */ 91 | public function getAttachments () 92 | { 93 | $attachments = []; 94 | $attach = $this->config->loadArray($this->getCFGDef('attachments')); 95 | $formfiles = $this->getFormData('files'); 96 | foreach ($attach as $field) { 97 | if (!isset($formfiles[$field])) continue; 98 | $files = $formfiles[$field]; 99 | if (!isset($files[0])) { 100 | $files = array($files); 101 | } 102 | foreach ($files as $file) { 103 | if ($file['error'] === 0) { 104 | $attachments[] = array('filepath' => $file['tmp_name'], 'filename' => $file['name']); 105 | } 106 | } 107 | } 108 | $userfiles = $this->config->loadArray($this->getCFGDef('attachFiles')); 109 | foreach ($userfiles as $field => $files) { 110 | if (!isset($files[0])) { 111 | $files = array($files); 112 | } 113 | foreach ($files as $file) { 114 | if (isset($file['filepath']) && isset($file['filename'])) { 115 | $attachments[] = array( 116 | 'filepath' => MODX_BASE_PATH . $file['filepath'], 117 | 'filename' => $file['filename'] 118 | ); 119 | } 120 | } 121 | } 122 | 123 | return $attachments; 124 | } 125 | 126 | /** 127 | * @return $this 128 | */ 129 | public function setFileFields () 130 | { 131 | $fields = []; 132 | $attach = $this->config->loadArray($this->getCFGDef('attachments')); 133 | $formfiles = $this->getFormData('files'); 134 | foreach ($attach as $field) { 135 | if (!isset($formfiles[$field])) continue; 136 | $files = $formfiles[$field]; 137 | if (!isset($files[0])) { 138 | $files = array($files); 139 | } 140 | foreach ($files as $file) { 141 | if ($file['error'] === 0) { 142 | $fields[$field][] = $file['name']; 143 | } 144 | } 145 | } 146 | $userfiles = $this->config->loadArray($this->getCFGDef('attachFiles')); 147 | foreach ($userfiles as $field => $files) { 148 | if (!isset($files[0])) { 149 | $files = array($files); 150 | } 151 | foreach ($files as $file) { 152 | if (isset($file['filename']) && isset($file['filepath'])) { 153 | $fields[$field][] = $file['filename']; 154 | } 155 | } 156 | } 157 | if (!empty($fields)) { 158 | $this->setFields($fields); 159 | } 160 | 161 | return $this; 162 | } 163 | 164 | /** 165 | * Оправляет письмо 166 | * @return mixed 167 | */ 168 | public function sendReport () 169 | { 170 | $mailer = new Mailer($this->modx, array_merge( 171 | $this->mailConfig, 172 | ['subject' => $this->renderSubject()] 173 | )); 174 | $attachments = $this->getAttachments(); 175 | if ($attachments) { 176 | $mailer->attachFiles($attachments); 177 | $this->log('Attachments', $attachments); 178 | $field = []; 179 | foreach ($attachments as $file) { 180 | $field[] = $file['filename']; 181 | } 182 | $this->setField('attachments', $field); 183 | } 184 | $report = $this->renderReport(); 185 | $out = $mailer->send($report) || $this->getCFGDef('ignoreMailerResult', 0); 186 | $this->log('Mail report', [ 187 | 'report' => $report, 188 | 'mailer_config' => $mailer->config, 189 | 'result' => $out 190 | ]); 191 | 192 | return $out; 193 | } 194 | 195 | /** 196 | * Оправляет копию письма на указанный адрес 197 | * @return mixed 198 | */ 199 | public function sendAutosender () 200 | { 201 | $to = $this->getCFGDef('autosender', ''); 202 | 203 | $config = $this->getMailSendConfig($to, 'autosenderFromName', 'autoSubject'); 204 | $asConfig = $this->config->loadArray($this->getCFGDef('autoMailConfig')); 205 | if (!empty($asConfig) && is_array($asConfig)) { 206 | $asConfig = $this->parseMailerParams($asConfig); 207 | $config = array_merge($config, $asConfig); 208 | } 209 | $mailer = new Mailer($this->modx, $config); 210 | $report = $this->renderReport('automessageTpl'); 211 | $out = empty($to) ? true : $mailer->send($report); 212 | $this->log( 213 | 'Mail autosender report', 214 | [ 215 | 'report' => $report, 216 | 'mailer_config' => $mailer->config, 217 | 'result' => $out 218 | ] 219 | ); 220 | 221 | return $out; 222 | } 223 | 224 | /** 225 | * Отправляет копию письма на адрес из поля email 226 | * @return mixed 227 | */ 228 | public function sendCCSender () 229 | { 230 | $to = $this->getField($this->getCFGDef('ccSenderField', 'email'), ''); 231 | 232 | if ($this->getCFGDef('ccSender', 0)) { 233 | $config = $this->getMailSendConfig($to, 'ccSenderFromName', 'ccSubject'); 234 | $ccConfig = $this->config->loadArray($this->getCFGDef('ccMailConfig')); 235 | if (!empty($ccConfig) && is_array($ccConfig)) { 236 | $ccConfig = $this->parseMailerParams($ccConfig); 237 | $config = array_merge($config, $ccConfig); 238 | } 239 | $mailer = new Mailer($this->modx, $config); 240 | $report = $this->renderReport('ccSenderTpl'); 241 | $out = empty($to) ? true : $mailer->send($report); 242 | $this->log( 243 | 'Mail CC report', 244 | [ 245 | 'report' => $report, 246 | 'mailer_config' => $mailer->config, 247 | 'result' => $out 248 | ] 249 | ); 250 | } else { 251 | $out = true; 252 | } 253 | 254 | return $out; 255 | } 256 | 257 | /** 258 | * @return string 259 | */ 260 | public function render () 261 | { 262 | if ($this->isSubmitted() && ($this->checkSubmitLimit() || $this->checkSubmitProtection())) { 263 | return $this->renderForm(); 264 | } 265 | 266 | return parent::render(); 267 | } 268 | 269 | /** 270 | * 271 | */ 272 | public function process () 273 | { 274 | $now = time() + $this->modx->getConfig('server_offset_time'); 275 | $this->setField('form.date', date($this->getCFGDef('dateFormat', $this->translate('form.dateFormat')), $now)); 276 | $this->setFileFields(); 277 | $this->mailConfig = $this->parseMailerParams($this->mailConfig); 278 | if ($this->sendReport()) { 279 | $this->sendCCSender(); 280 | $this->sendAutosender(); 281 | $this->setSubmitProtection()->postProcess(); 282 | } else { 283 | $this->addMessage($this->translate('form.form_failed')); 284 | } 285 | } 286 | 287 | /** 288 | * @param array $cfg 289 | * @return array 290 | */ 291 | public function parseMailerParams ($cfg = []) 292 | { 293 | if ($this->getCFGDef('parseMailerParams', 0) && !empty($cfg)) { 294 | $plh = \APIhelpers::renameKeyArr($this->prerenderForm(true), '[', ']', '+'); 295 | $search = array_keys($plh); 296 | $replace = array_values($plh); 297 | foreach ($cfg as $key => &$value) { 298 | if(empty($value)) continue; 299 | $value = str_replace($search, $replace, $value); 300 | } 301 | $config = \APIhelpers::renameKeyArr($this->modx->config, '[(', ')]', ''); 302 | $search = array_keys($config); 303 | $replace = array_values($config); 304 | foreach ($cfg as $key => &$value) { 305 | $value = str_replace($search, $replace, $value); 306 | } 307 | } 308 | 309 | return $cfg; 310 | } 311 | 312 | /** 313 | * 314 | */ 315 | public function postProcess () 316 | { 317 | $this->setFormStatus(true); 318 | $this->runPrepare('prepareAfterProcess'); 319 | if ($this->getCFGDef('deleteAttachments', 0)) { 320 | $this->deleteAttachments(); 321 | } 322 | $this->redirect(); 323 | $tpl = $this->getCFGDef('successTpl', $this->translate('form.default_successTpl')); 324 | if (!empty($tpl)) { 325 | $this->renderTpl = $tpl; 326 | } 327 | } 328 | 329 | /** 330 | * @param string $to 331 | * @param string $fromParam 332 | * @param string $subjectParam 333 | * @return array 334 | */ 335 | public function getMailSendConfig ($to, $fromParam, $subjectParam = 'subject') 336 | { 337 | $subject = $this->renderSubject($subjectParam); 338 | 339 | $out = array_merge( 340 | $this->mailConfig, 341 | [ 342 | 'subject' => $subject, 343 | 'to' => $to, 344 | 'fromName' => $this->getCFGDef($fromParam, $this->modx->getConfig('site_name')) 345 | ] 346 | ); 347 | $out = $this->parseMailerParams($out); 348 | 349 | return $out; 350 | } 351 | 352 | /** 353 | * @return $this 354 | */ 355 | public function deleteAttachments () 356 | { 357 | $files = $this->getAttachments(); 358 | foreach ($files as $file) { 359 | $this->fs->delete($file['filepath']); 360 | } 361 | 362 | return $this; 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Login.php: -------------------------------------------------------------------------------- 1 | user = $this->loadModel( 37 | $this->getCFGDef('model', '\modUsers'), 38 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 39 | ); 40 | $requestUri = $_SERVER['REQUEST_URI']; 41 | if (0 === strpos($requestUri, MODX_BASE_URL)) { 42 | $requestUri = substr($requestUri, strlen(MODX_BASE_URL)); 43 | } 44 | $this->requestUri = $this->modx->getConfig('site_url') . $requestUri; 45 | $this->context = $this->getCFGDef('context', 'web'); 46 | $this->lexicon->fromFile('login'); 47 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 48 | $this->dateFormat = $this->getCFGDef('dateFormat', ''); 49 | } 50 | 51 | /** 52 | * @return string 53 | */ 54 | public function render() 55 | { 56 | if ($id = $this->modx->getLoginUserID($this->context)) { 57 | $this->redirect('exitTo'); 58 | $this->user->edit($id); 59 | $this->setFields($this->user->toArray()); 60 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->lexicon->getMsg('login.default_skipTpl')); 61 | $this->setValid(false); 62 | }; 63 | 64 | return parent::render(); 65 | } 66 | 67 | 68 | /** 69 | * 70 | */ 71 | public function process() 72 | { 73 | if (is_null($this->user)) { 74 | $this->addMessage($this->lexicon->getMsg('login.user_failed')); 75 | 76 | return; 77 | } 78 | $login = $this->getField($this->getCFGDef('loginField', 'username')); 79 | if (!is_scalar($login)) { 80 | $login = ''; 81 | } 82 | $password = $this->getField($this->getCFGDef('passwordField', 'password')); 83 | $remember = $this->getField($this->getCFGDef('rememberField', 'rememberme')); 84 | if ($this->user->checkBlock($login)) { 85 | $this->addMessage($this->lexicon->getMsg('login.user_blocked')); 86 | 87 | return; 88 | } 89 | $this->user->edit($login); 90 | 91 | if ($this->getCFGDef('checkActivation', 0) && !$this->user->get('verified')) { 92 | $this->addMessage($this->lexicon->getMsg('login.user_notactivated')); 93 | 94 | return; 95 | } 96 | 97 | $auth = $this->user->testAuth($login, $password, false, true); 98 | if (!$auth) { 99 | $this->addMessage($this->lexicon->getMsg('login.user_failed')); 100 | 101 | return; 102 | } 103 | if ($remember) { 104 | $remember = $this->getCFGDef('cookieLifetime', 60 * 60 * 24 * 365 * 5); 105 | } 106 | $loginCookie = $this->getCFGDef('cookieName', 'WebLoginPE'); 107 | $this->user->authUser($login, $remember, $loginCookie, true); 108 | $this->setFormStatus(true); 109 | $this->runPrepare('prepareAfterProcess'); 110 | if (isset($this->modx->documentIdentifier) && $this->modx->documentIdentifier == $this->modx->getConfig('unauthorized_page')) { 111 | $uaPage = $this->modx->makeUrl($this->modx->getConfig('unauthorized_page'), "", "", "full"); 112 | $requested = explode('?', $this->requestUri); 113 | if (array_shift($requested) != $uaPage) { 114 | $this->setField('redirectTo', $this->requestUri); 115 | $this->sendRedirect($this->requestUri); 116 | } else { 117 | $this->redirect(); 118 | } 119 | } else { 120 | $this->redirect(); 121 | } 122 | $this->setFields($this->user->toArray()); 123 | if ($dob = $this->fromTimestamp($this->getField('dob'))) { 124 | $this->setField('dob', $dob); 125 | } 126 | $this->renderTpl = $this->getCFGDef('successTpl'); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/MailChimp.php: -------------------------------------------------------------------------------- 1 | lexicon->fromFile('mailchimp'); 20 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 21 | } 22 | 23 | /** 24 | * @return bool 25 | */ 26 | public function process() 27 | { 28 | $errorMessage = $this->translate('mc.subscription_failed'); 29 | if (!$this->getCFGDef('apiKey')) { 30 | $this->addMessage($errorMessage); 31 | 32 | return false; 33 | } 34 | $MailChimp = new \DrewM\MailChimp\MailChimp($this->getCFGDef('apiKey')); 35 | $list_id = $this->getCFGDef('listId'); 36 | if (!$list_id) { 37 | $this->addMessage($errorMessage); 38 | 39 | return false; 40 | } 41 | 42 | $MailChimp->post("lists/{$list_id}/members", [ 43 | 'email_address' => $this->getField('email'), 44 | 'merge_fields' => ['NAME' => $this->getField('name')], 45 | 'status' => 'pending', 46 | ]); 47 | if (!$MailChimp->getLastError()) { 48 | $this->addMessage($errorMessage); 49 | 50 | return false; 51 | } else { 52 | $this->setFormStatus(true); 53 | $this->runPrepare('prepareAfterProcess'); 54 | $this->renderTpl = $this->getCFGDef('successTpl', $this->translate('mc.default_successTpl')); 55 | 56 | return true; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Profile.php: -------------------------------------------------------------------------------- 1 | lexicon->fromFile('profile'); 29 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 30 | $uid = (int)$modx->getLoginUserId('web'); 31 | if ($uid) { 32 | /* @var $user \modUsers */ 33 | $user = $this->loadModel( 34 | $this->getCFGDef('model', '\modUsers'), 35 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 36 | ); 37 | $this->user = $user->edit($uid); 38 | $this->config->setConfig([ 39 | 'userdata' => $this->user->toArray() 40 | ]); 41 | } 42 | $this->dateFormat = $this->getCFGDef('dateFormat', ''); 43 | } 44 | 45 | /** 46 | * Загружает в formData данные не из формы 47 | * @param string $sources список источников 48 | * @param string $arrayParam название параметра с данными 49 | * @return $this 50 | */ 51 | public function setExternalFields ($sources = 'array', $arrayParam = 'defaults') 52 | { 53 | parent::setExternalFields($sources, $arrayParam); 54 | parent::setExternalFields('array', 'userdata'); 55 | 56 | return $this; 57 | } 58 | 59 | 60 | /** 61 | * @return string 62 | */ 63 | public function render () 64 | { 65 | if (is_null($this->user) || !$this->user->getID()) { 66 | $this->redirect('exitTo'); 67 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->translate('profile.default_skipTpl')); 68 | $this->setValid(false); 69 | } 70 | if (!$this->isSubmitted() && ($dob = $this->getField('dob'))) { 71 | $this->setField('dob', $this->fromTimestamp($dob)); 72 | } 73 | 74 | return parent::render(); 75 | } 76 | 77 | public function getValidationRules($param = 'rules') 78 | { 79 | $rules = parent::getValidationRules($param); // TODO: Change the autogenerated stub 80 | $password = $this->getField('password'); 81 | if (empty($password) || !is_scalar($password)) { 82 | $this->forbiddenFields[] = 'password'; 83 | if (isset($rules['password'])) { 84 | unset($rules['password']); 85 | } 86 | if (isset($rules['repeatPassword'])) { 87 | unset($rules['repeatPassword']); 88 | } 89 | } else { 90 | if (isset($rules['repeatPassword']['equals'])) { 91 | $rules['repeatPassword']['equals']['params'] = $this->getField('password'); 92 | } 93 | } 94 | 95 | return $rules; 96 | } 97 | 98 | /** 99 | * @param $fl 100 | * @param $value 101 | * @return bool 102 | */ 103 | public static function uniqueEmail ($fl, $value) 104 | { 105 | $result = true; 106 | if (is_scalar($value) && !is_null($fl->user) && ($fl->user->get("email") !== $value)) { 107 | /* @var $user \modUsers */ 108 | $user = clone($fl->user); 109 | $user->set('email', $value); 110 | $result = $user->isUnique('email'); 111 | } 112 | 113 | return $result; 114 | } 115 | 116 | /** 117 | * @param $fl 118 | * @param $value 119 | * @return bool 120 | */ 121 | public static function uniqueUsername ($fl, $value) 122 | { 123 | $result = true; 124 | if (is_scalar($value) && !is_null($fl->user) && ($fl->user->get("email") !== $value)) { 125 | /* @var $user \modUsers */ 126 | $user = clone($fl->user); 127 | $user->set('username', $value); 128 | $result = $user->isUnique('username'); 129 | } 130 | 131 | return $result; 132 | } 133 | 134 | /** 135 | * 136 | */ 137 | public function process () 138 | { 139 | if ($this->user->get('username') == $this->user->get('email') && !empty($this->getField('email')) && empty($this->getField('username'))) { 140 | $this->setField('username', $this->getField('email')); 141 | if (!empty($this->allowedFields)) { 142 | $this->allowedFields[] = 'username'; 143 | } 144 | if (!empty($this->forbiddenFields)) { 145 | $_forbidden = array_flip($this->forbiddenFields); 146 | unset($_forbidden['username']); 147 | $this->forbiddenFields = array_keys($_forbidden); 148 | } 149 | } 150 | 151 | $newpassword = $this->getField('password'); 152 | $password = $this->user->get('password'); 153 | if (!empty($newpassword) && ($password !== $this->user->getPassword($newpassword))) { 154 | if (!empty($this->allowedFields)) { 155 | $this->allowedFields[] = 'password'; 156 | } 157 | if (!empty($this->forbiddenFields)) { 158 | $_forbidden = array_flip($this->forbiddenFields); 159 | unset($_forbidden['password']); 160 | $this->forbiddenFields = array_keys($_forbidden); 161 | } 162 | } 163 | $fields = $this->filterFields($this->getFormData('fields'), $this->allowedFields, $this->forbiddenFields); 164 | if (isset($fields['username'])) { 165 | $fields['username'] = is_scalar($fields['username']) ? $fields['username'] : ''; 166 | } 167 | if (isset($fields['email'])) { 168 | $fields['email'] = is_scalar($fields['email']) ? $fields['email'] : ''; 169 | } 170 | if (isset($fields['dob']) && ($dob = $this->toTimestamp($fields['dob']))) { 171 | $fields['dob'] = $dob; 172 | } 173 | $verificationField = $this->getCFGDef('verificationField', 'email'); 174 | if (isset($fields[$verificationField]) && $this->user->get($verificationField) != $fields[$verificationField]) { 175 | $fields['verified'] = 0; 176 | } 177 | $result = (int)$this->user->fromArray($fields)->save(true); 178 | $this->log('Update profile', [ 179 | 'data' => $fields, 180 | 'result' => $result, 181 | 'log' => $this->user->getLog() 182 | ]); 183 | if ($result) { 184 | $this->setFormStatus(true); 185 | $this->user->close(); 186 | $this->setFields($this->user->edit($result)->toArray()); 187 | if ($dob = $this->fromTimestamp($this->getField('dob'))) { 188 | $this->setField('dob', $dob); 189 | } 190 | $this->setField('user.password', $newpassword); 191 | $this->runPrepare('preparePostProcess'); 192 | $this->runPrepare('prepareAfterProcess'); 193 | $checkActivation = $this->getCFGDef('checkActivation', 0); 194 | if ($checkActivation && !$this->getField('verified')) { 195 | $this->user->logOut('WebLoginPE', true); 196 | $this->redirect('exitTo'); 197 | } 198 | $this->redirect(); 199 | if ($successTpl = $this->getCFGDef('successTpl')) { 200 | $this->renderTpl = $successTpl; 201 | } else { 202 | $this->addMessage($this->translate('profile.update_success')); 203 | } 204 | } else { 205 | $this->addMessage($this->translate('profile.update_failed')); 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Register.php: -------------------------------------------------------------------------------- 1 | user = $this->loadModel( 31 | $this->getCFGDef('model', '\modUsers'), 32 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 33 | ); 34 | $this->lexicon->fromFile('register'); 35 | $this->log('Lexicon loaded', ['lexicon' => $this->lexicon->getLexicon()]); 36 | $this->dateFormat = $this->getCFGDef('dateFormat', ''); 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function render () 43 | { 44 | if ($id = $this->modx->getLoginUserID('web')) { 45 | $this->redirect('exitTo'); 46 | $this->user->edit($id); 47 | $this->setFields($this->user->toArray()); 48 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->translate('register.default_skipTpl')); 49 | $this->setValid(false); 50 | }; 51 | 52 | return parent::render(); 53 | } 54 | 55 | public function getValidationRules($param = 'rules') 56 | { 57 | $rules = parent::getValidationRules($param); // TODO: Change the autogenerated stub 58 | if (isset($rules['password']) && isset($rules['repeatPassword']) && !empty($this->getField('password')) && isset($this->rules['repeatPassword']['equals'])) { 59 | $rules['repeatPassword']['equals']['params'] = $this->getField('password'); 60 | } 61 | 62 | return $rules; 63 | } 64 | 65 | /** 66 | * Custom validation rule 67 | * Проверяет уникальность email 68 | * @param $fl 69 | * @param $value 70 | * @return bool 71 | */ 72 | public static function uniqueEmail ($fl, $value) 73 | { 74 | $result = true; 75 | if (is_scalar($value) && !is_null($fl->user)) { 76 | $fl->user->set('email', $value); 77 | $result = $fl->user->isUnique('email'); 78 | } 79 | 80 | return $result; 81 | } 82 | 83 | /** 84 | * Custom validation rule 85 | * Проверяет уникальность имени пользователя 86 | * @param $fl 87 | * @param $value 88 | * @return bool 89 | */ 90 | public static function uniqueUsername ($fl, $value) 91 | { 92 | $result = true; 93 | if (is_scalar($value) && !is_null($fl->user)) { 94 | $fl->user->set('username', $value); 95 | $result = $fl->user->isUnique('username'); 96 | } 97 | 98 | return $result; 99 | } 100 | 101 | /** 102 | * 103 | */ 104 | public function process () 105 | { 106 | if (!empty($this->allowedFields)) { 107 | $this->allowedFields[] = 'username'; 108 | $this->allowedFields[] = 'password'; 109 | $this->allowedFields[] = 'email'; 110 | } 111 | if (!empty($this->forbiddenFields)) { 112 | $_forbidden = array_flip($this->forbiddenFields); 113 | unset($_forbidden['username'], $_forbidden['password'], $_forbidden['email']); 114 | $this->forbiddenFields = array_keys($_forbidden); 115 | } 116 | 117 | //регистрация без логина, по емейлу 118 | if ($this->getField('username') == '') { 119 | $this->setField('username', $this->getField('email')); 120 | } 121 | //регистрация со случайным паролем 122 | if ($this->getField('password') == '' && !isset($this->rules['password'])) { 123 | $this->setField('password', APIhelpers::genPass($this->getCFGDef('passwordLength', 6))); 124 | } 125 | $password = $this->getField('password'); 126 | $fields = $this->filterFields($this->getFormData('fields'), $this->allowedFields, $this->forbiddenFields); 127 | if (isset($fields['dob']) && ($dob = $this->toTimestamp($fields['dob']))) { 128 | $fields['dob'] = $dob; 129 | } 130 | $checkActivation = $this->getCFGDef('checkActivation', 0); 131 | $fields['verified'] = (int)!$checkActivation; 132 | $fields['username'] = is_scalar($fields['username']) ? $fields['username'] : ''; 133 | $fields['email'] = is_scalar($fields['email']) ? $fields['email'] : ''; 134 | $fields['role'] = (int)$this->getCFGDef('userRole', 0); 135 | $this->user->create($fields); 136 | $this->user->setUserGroupsByName(0, $this->config->loadArray($this->getCFGDef('userGroups'))); 137 | $result = $this->user->save(true); 138 | $this->log('Register user', [ 139 | 'data' => $fields, 140 | 'result' => $result, 141 | 'log' => $this->user->getLog() 142 | ]); 143 | if (!$result) { 144 | $this->addMessage($this->translate('register.registration_failed')); 145 | } else { 146 | $this->user->close(); 147 | $userdata = $this->user->edit((int)$result)->toArray(); 148 | $this->setFields($userdata); 149 | if ($dob = $this->fromTimestamp($this->getField('dob'))) { 150 | $this->setField('dob', $dob); 151 | } 152 | $this->setField('user.password', $password); 153 | $this->runPrepare('preparePostProcess'); 154 | if ($checkActivation) { 155 | $hash = md5(jsonHelper::toJSON($userdata)); 156 | $uidName = $this->getCFGDef('uidName', $this->user->fieldPKName()); 157 | $query = http_build_query([ 158 | $uidName => $result, 159 | 'hash' => $hash 160 | ]); 161 | $url = $this->getCFGDef('activateTo', isset($this->modx->documentIdentifier) && $this->modx->documentIdentifier > 0 ? $this->modx->documentIdentifier : $this->modx->getConfig('site_start')); 162 | if(is_numeric($url)) { 163 | $url = $this->modx->makeUrl($url, "", $query, 'full'); 164 | } else { 165 | $url = $this->modx->getConfig('site_url') . $url . '?' . $query; 166 | } 167 | $this->setField('activate.url', $url); 168 | } 169 | parent::process(); 170 | } 171 | } 172 | 173 | /** 174 | * 175 | */ 176 | public function postProcess () 177 | { 178 | parent::postProcess(); 179 | $tpl = $this->getCFGDef('successTpl', $this->translate('register.default_successTpl')); 180 | if (!empty($tpl)) { 181 | $this->renderTpl = $tpl; 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/controller/Reminder.php: -------------------------------------------------------------------------------- 1 | user = $this->loadModel( 50 | $this->getCFGDef('model', '\modUsers'), 51 | $this->getCFGDef('modelPath', 'assets/lib/MODxAPI/modUsers.php') 52 | ); 53 | $this->lexicon->fromFile('reminder'); 54 | $this->log('Lexicon loaded', array('lexicon' => $this->lexicon->getLexicon())); 55 | $hashField = $this->getCFGDef('hashField', 'hash'); 56 | $uidField = $this->getCFGDef('uidField', $this->user->fieldPKName()); 57 | $uidName = $this->getCFGDef('uidName', $uidField); 58 | $userField = $this->getCFGDef('userField', 'email'); 59 | $this->hashField = $hashField; 60 | $this->uidField = $uidField; 61 | $this->userField = $userField; 62 | $this->uidName = $uidName; 63 | $this->config->setConfig([ 64 | 'protectSubmit' => 0 65 | ]); 66 | if ((isset($_REQUEST[$hashField]) && !empty($_REQUEST[$hashField])) && (isset($_REQUEST[$uidName]) && !empty($_REQUEST[$uidName]))) { 67 | $this->setFields($_REQUEST); 68 | $this->mode = 'reset'; 69 | $this->config->setConfig([ 70 | 'rules' => $this->getCFGDef('resetRules'), 71 | 'reportTpl' => $this->getCFGDef('resetReportTpl'), 72 | 'submitLimit' => 0 73 | ]); 74 | } 75 | $this->log('Reminder mode is ' . $this->mode); 76 | } 77 | 78 | /** 79 | * @return string 80 | */ 81 | public function render () 82 | { 83 | if ($id = (int)$this->modx->getLoginUserID('web')) { 84 | $this->redirect('exitTo'); 85 | $this->user->edit($id); 86 | $this->setFields($this->user->toArray()); 87 | $this->renderTpl = $this->getCFGDef('skipTpl', $this->translate('reminder.default_skipTpl')); 88 | $this->setValid(false); 89 | } 90 | 91 | if ($this->mode == 'reset') { 92 | $this->renderReset(); 93 | } 94 | 95 | return parent::render(); 96 | } 97 | 98 | 99 | /** 100 | * 101 | */ 102 | public function renderReset () 103 | { 104 | $hash = $this->getField($this->hashField); 105 | $uid = $this->getField($this->uidName); 106 | $uid = (int)$uid; 107 | $_hash = $this->getUserHash($uid); 108 | if (is_scalar($hash) && $hash && $hash == $_hash) { 109 | if ($this->getCFGDef('resetTpl')) { 110 | $this->setField('user.hash', $hash); 111 | $this->setField('user.id', $uid); 112 | $this->renderTpl = $this->getCFGDef('resetTpl'); 113 | 114 | return; 115 | } 116 | $this->process(); 117 | } else { 118 | $this->addMessage($this->translate('reminder.update_failed')); 119 | } 120 | } 121 | 122 | public function getValidationRules($param = 'rules') 123 | { 124 | $rules = parent::getValidationRules($param); // TODO: Change the autogenerated stub 125 | if (isset($rules['password']) && isset($rules['repeatPassword']) && !empty($this->getField('password')) && isset($this->rules['repeatPassword']['equals'])) { 126 | $rules['repeatPassword']['equals']['params'] = $this->getField('password'); 127 | } 128 | 129 | return $rules; 130 | } 131 | 132 | /** 133 | * @param $uid 134 | * @return bool|string 135 | */ 136 | public function getUserHash ($uid) 137 | { 138 | if (is_null($this->user)) { 139 | $hash = false; 140 | } else { 141 | $userdata = $this->user->edit($uid)->toArray(); 142 | $hash = $this->user->getID() ? md5(jsonHelper::toJSON($userdata)) : false; 143 | } 144 | 145 | return $hash; 146 | } 147 | 148 | /** 149 | * 150 | */ 151 | public function process () 152 | { 153 | switch ($this->mode) { 154 | /** 155 | * Задаем хэш, отправляем пользователю ссылку для восстановления пароля 156 | */ 157 | case "hash": 158 | $user = $this->getField($this->userField); 159 | if ($hash = $this->getUserHash($user)) { 160 | $this->setFields($this->user->toArray()); 161 | $url = $this->getCFGDef('resetTo', 162 | isset($this->modx->documentIdentifier) && $this->modx->documentIdentifier > 0 ? $this->modx->documentIdentifier : $this->modx->getConfig('site_start')); 163 | $uidName = $this->getCFGDef('uidName', $this->uidField); 164 | $query = http_build_query([$uidName => $this->getField($this->uidField), $this->hashField => $hash]); 165 | if(is_numeric($url)) { 166 | $url = $this->modx->makeUrl($url, "", $query, 'full'); 167 | } else { 168 | $url .= '?' . $query; 169 | } 170 | $this->setField('reset.url', $url); 171 | $this->mailConfig['to'] = $this->user->get('email'); 172 | parent::process(); 173 | } else { 174 | $this->addMessage($this->translate('reminder.users_only')); 175 | } 176 | break; 177 | /** 178 | * Если пароль не задан, то создаем пароль 179 | * Отправляем пользователю письмо с паролем, если указан шаблон такого письма 180 | * Если не указан, то запрещаем отправку письма, пароль будет показан на экране 181 | */ 182 | case "reset": 183 | $uid = (int)$this->getField($this->uidName); 184 | $hash = $this->getField($this->hashField); 185 | if ($hash && $hash == $this->getUserHash($uid)) { 186 | if ($this->getField('password') == '' && !isset($this->rules['password'])) { 187 | $this->setField('password', APIhelpers::genPass($this->getCFGDef('passwordLength', 6))); 188 | } 189 | $fields = $this->filterFields($this->getFormData('fields'), array($this->userField, 'password')); 190 | $result = $this->user->edit($uid)->fromArray($fields)->save(true); 191 | $this->log('Update password', ['data' => $fields, 'result' => $result]); 192 | if (!$result) { 193 | $this->addMessage($this->translate('reminder.update_failed')); 194 | } else { 195 | $this->setField('newpassword', $this->getField('password')); 196 | $this->setFields($this->user->toArray()); 197 | $this->mailConfig['to'] = $this->getField('email'); 198 | parent::process(); 199 | } 200 | } else { 201 | $this->addMessage($this->translate('reminder.update_failed')); 202 | } 203 | break; 204 | } 205 | } 206 | 207 | /** 208 | * @return string 209 | */ 210 | public function getMode() { 211 | return $this->mode; 212 | } 213 | 214 | /** 215 | * 216 | */ 217 | public function postProcess () 218 | { 219 | $this->setFormStatus(true); 220 | $this->runPrepare('prepareAfterProcess'); 221 | switch ($this->mode) { 222 | case 'hash': 223 | $this->renderTpl = $this->getCFGDef('successTpl', 224 | $this->translate('reminder.default_successTpl')); 225 | break; 226 | case 'reset': 227 | default: 228 | $this->redirect(); 229 | $this->renderTpl = $this->getCFGDef('resetSuccessTpl', 230 | $this->translate('reminder.default_resetSuccessTpl')); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/de/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+activate.url+]'; 12 | $_lang['activate.no_activation'] = 'Dieses Konto muss nicht, oder kann nicht aktiviert werden.'; 13 | $_lang['activate.update_failed'] = 'Fehler beim Fortfahren.'; 14 | $_lang['activate.default_successTpl'] = '@CODE:Der Link zum Aktivieren Ihres Kontos wurde gesendet.'; 15 | $_lang['activate.default_resetSuccessTpl'] = '@CODE:Dein Benutzerkonto ist aktiv.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/de/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Die Authentifizierung der Anfrage ist fehlgeschlagen' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/de/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 12 | $_lang['reminder.users_only'] = 'Nur registrierte Benutzer können Passwörter wiederherstellen.'; 13 | $_lang['reminder.update_failed'] = 'Fehler beim Fortfahren.'; 14 | $_lang['reminder.default_successTpl'] = '@CODE:Der Link zum Wiederherstellen Ihres Passworts wurde gesendet.'; 15 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:Das neue Passwort wurde gesendet.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/en/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+activate.url+]'; 12 | $_lang['activate.no_activation'] = 'This user account need no activation or cannot be activated.'; 13 | $_lang['activate.update_failed'] = 'Failed to proceed.'; 14 | $_lang['activate.default_successTpl'] = '@CODE:The link to activate your account has been mailed.'; 15 | $_lang['activate.default_resetSuccessTpl'] = '@CODE:Your account is activated.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/en/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Failed to authenticate request' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/en/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 12 | $_lang['reminder.users_only'] = 'Only registered users can restore passwords.'; 13 | $_lang['reminder.update_failed'] = 'Failed to proceed.'; 14 | $_lang['reminder.default_successTpl'] = '@CODE:The link to restore your password has been mailed.'; 15 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:New password has been mailed.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/es/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+activate.url+]'; 12 | $_lang['activate.no_activation'] = 'Esta cuenta de usuario no necesita activación o no puede ser activada.'; 13 | $_lang['activate.update_failed'] = 'Fallo al proceder.'; 14 | $_lang['activate.default_successTpl'] = '@CODE:El enlace para activar su cuenta ha sido enviado.'; 15 | $_lang['activate.default_resetSuccessTpl'] = '@CODE:Tu cuenta está activa.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/es/content.inc.php: -------------------------------------------------------------------------------- 1 | 'No se pudo autenticar la solicitud' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/es/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 12 | $_lang['reminder.users_only'] = 'Solo los usuarios registrados pueden restaurar contraseñas.'; 13 | $_lang['reminder.update_failed'] = 'Fallo al proceder.'; 14 | $_lang['reminder.default_successTpl'] = '@CODE:El enlace para restaurar su contraseña ha sido enviado.'; 15 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:La nueva contraseña ha sido enviada.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/it/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+activate.url+]'; 12 | $_lang['activate.no_activation'] = 'Questo account utente non ha bisogno di attivazione o non può essere attivato.'; 13 | $_lang['activate.update_failed'] = 'Impossibile procedere.'; 14 | $_lang['activate.default_successTpl'] = '@CODE:Il link per attivare il tuo account è stato inviato via mail.'; 15 | $_lang['activate.default_resetSuccessTpl'] = '@CODE:Il tuo account è attivato.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/it/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Impossibile autenticare la richiesta' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/it/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 12 | $_lang['reminder.users_only'] = 'Solo gli utenti registrati possono ripristinare le password.'; 13 | $_lang['reminder.update_failed'] = 'Impossibile procedere.'; 14 | $_lang['reminder.default_successTpl'] = '@CODE:Il link per ripristinare la password è stato inviato per posta.'; 15 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:La nuova password è stata inviata via mail.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/nl/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+activate.url+]'; 12 | $_lang['activate.no_activation'] = 'Dit gebruikersaccount hoeft niet te worden geactiveerd of kan niet worden geactiveerd.'; 13 | $_lang['activate.update_failed'] = 'Update mislukt.'; 14 | $_lang['activate.default_successTpl'] = '@CODE:De link om uw account te activeren is gemaild.'; 15 | $_lang['activate.default_resetSuccessTpl'] = '@CODE:Uw account is geactiveerd.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/nl/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Kan het verzoek niet verifiëren' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/nl/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 12 | $_lang['reminder.users_only'] = 'Alleen geregistreerde gebruikers kunnen wachtwoorden herstellen.'; 13 | $_lang['reminder.update_failed'] = 'Kan niet doorgaan.'; 14 | $_lang['reminder.default_successTpl'] = '@CODE:De link om uw wachtwoord te herstellen is gemaild.'; 15 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:Nieuw wachtwoord is gemaild.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/pl/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+activate.url+]'; 12 | $_lang['activate.no_activation'] = 'To konto nie potrzebuje aktywacji lub nie może zostać aktywowane.'; 13 | $_lang['activate.update_failed'] = 'Akcja zakończona niepowodzeniem.'; 14 | $_lang['activate.default_successTpl'] = '@CODE:Wiadomość z linkiem aktywacyjnym została wysłana na wskazany adres e-mail.'; 15 | $_lang['activate.default_resetSuccessTpl'] = '@CODE:Twoje konto zostało aktywowane.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/pl/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Nie udało się uwierzytelnić żądania' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/pl/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 12 | $_lang['reminder.users_only'] = 'Tylko zarejestrowani użytkownicy mogą zresetować hasło.'; 13 | $_lang['reminder.update_failed'] = 'Akcja zakończona niepowodzeniem.'; 14 | $_lang['reminder.default_successTpl'] = '@CODE:Wiadomość z linkiem resetującym hasło została wysłana na wskazany adres e-mail.'; 15 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:Nowe hasło zostało wysłane na wskazany adres e-mail.'; 16 | 17 | return $_lang; 18 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/ru/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 14 | $_lang['activate.no_activation'] = 'Эта учетная запись не требует активации или не может быть активирована.'; 15 | $_lang['activate.update_failed'] = 'Не удалось выполнить операцию.'; 16 | $_lang['activate.default_successTpl'] = '@CODE:Вам отправлено письмо со ссылкой для активации учетной записи.'; 17 | $_lang['activate.default_activateSuccessTpl'] = '@CODE:Учетная запись успешно активирована.'; 18 | 19 | return $_lang; 20 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/ru/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Не удалось проверить подлинность запроса' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/ru/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 14 | $_lang['reminder.users_only'] = 'Только зарегистрированные пользователи могут восстанавливать пароли.'; 15 | $_lang['reminder.update_failed'] = 'Не удалось выполнить операцию.'; 16 | $_lang['reminder.default_successTpl'] = '@CODE:Вам отправлено письмо со ссылкой для восстановления пароля.'; 17 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:Вам отправлено письмо с новым паролем.'; 18 | 19 | return $_lang; 20 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/uk/activate.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 14 | $_lang['activate.no_activation'] = 'Цей обліковий запис не вимагає активації або не може бути активованим.'; 15 | $_lang['activate.update_failed'] = 'Не вдалося виконати операцію.'; 16 | $_lang['activate.default_successTpl'] = '@CODE:Вам відправлено лист з посиланням для активації облікового запису.'; 17 | $_lang['activate.default_activateSuccessTpl'] = '@CODE:Обліковий запис успішно активований.'; 18 | 19 | return $_lang; 20 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/uk/content.inc.php: -------------------------------------------------------------------------------- 1 | 'Неможливо перевірити справжність запиту' 4 | ]; 5 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/core/lang/uk/deleteContent.inc.php: -------------------------------------------------------------------------------- 1 | [+reset.url+]'; 14 | $_lang['reminder.users_only'] = 'Тільки зареєстровані користувачі можуть відновлювати паролі.'; 15 | $_lang['reminder.update_failed'] = 'Не вдалося виконати операцію.'; 16 | $_lang['reminder.default_successTpl'] = '@CODE:Вам відправлено лист з посиланням для відновлення пароля.'; 17 | $_lang['reminder.default_resetSuccessTpl'] = '@CODE:Вам відправлено лист з новим паролем.'; 18 | 19 | return $_lang; 20 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/DateConverter.php: -------------------------------------------------------------------------------- 1 | dateFormat)) { 19 | $date = DateTime::createFromFormat($this->dateFormat, $value); 20 | if ($date !== false) { 21 | $date = $date->getTimestamp(); 22 | } 23 | } 24 | 25 | return $date; 26 | } 27 | 28 | /** 29 | * @param $value 30 | */ 31 | public function fromTimestamp($value) { 32 | $date = false; 33 | if (!empty($value) && !empty($this->dateFormat)) { 34 | $date = date($this->dateFormat, $value); 35 | } 36 | 37 | return $date; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/Debug.php: -------------------------------------------------------------------------------- 1 | modx = $modx; 29 | $this->timeStart = microtime(true); 30 | if (isset($cfg['caller'])) { 31 | $this->caller = $cfg['caller']; 32 | } 33 | } 34 | 35 | /** 36 | * @param $message 37 | * @param array $data 38 | */ 39 | public function log($message, $data = array()) 40 | { 41 | if (is_array($data) && isset($data[0]) && is_array($data[0])) { 42 | $data = array_pop($data); 43 | } 44 | $this->log[] = array( 45 | 'message' => $message, 46 | 'data' => $this->dumpData($data, 'pre'), 47 | 'time' => microtime(true) - $this->timeStart 48 | ); 49 | } 50 | 51 | /** 52 | * @param $data 53 | * @param string $wrap 54 | * @param string $charset 55 | * @return array|mixed|string 56 | */ 57 | public function dumpData($data, $wrap = '', $charset = 'UTF-8') 58 | { 59 | $out = \APIHelpers::sanitarTag(print_r($this->cleanData($data), 1), $charset); 60 | if (!empty($wrap) && is_string($wrap)) { 61 | $out = "<{$wrap}>{$out}"; 62 | } 63 | 64 | return $out; 65 | } 66 | 67 | /** 68 | * @param $data 69 | * @return array 70 | */ 71 | public function cleanData($data) { 72 | if (is_array($data)) { 73 | foreach ($data as $key => $value) { 74 | if (is_object($value)) { 75 | $data[$key] = 'Object: ' . get_class($value); 76 | } elseif (is_array($value)) { 77 | $data[$key] = $this->cleanData($value); 78 | } 79 | } 80 | if (empty($data)) { 81 | $data = 'No data provided' . PHP_EOL; 82 | } 83 | } 84 | 85 | return $data; 86 | } 87 | 88 | public function saveLog() 89 | { 90 | $out = ''; 91 | foreach ($this->log as $entry) { 92 | $out .= "

{$entry['message']}

"; 93 | if ($entry['data']) { 94 | $out .= $entry['data']; 95 | } 96 | $out .= "

Time: {$entry['time']}

"; 97 | $out .= '
'; 98 | } 99 | $time = microtime(true) - $this->timeStart; 100 | $out .= "

Total time: {$time}

"; 101 | if ($out) { 102 | $this->modx->logEvent(0, 1, $out, $this->caller); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/FileValidator.php: -------------------------------------------------------------------------------- 1 | $min : $size >= $min; 99 | if (!$flag) { 100 | break; 101 | } 102 | } 103 | 104 | return $flag; 105 | } 106 | 107 | /** 108 | * @param $value 109 | * @param $min 110 | * @param $max 111 | * @param bool $strict 112 | * @return bool 113 | */ 114 | public static function sizeBetween($value, $min, $max, $strict = false): bool 115 | { 116 | $value = self::value($value); 117 | $flag = false; 118 | foreach ($value as $file) { 119 | $size = round($file['size'] / 1024, 0); 120 | $flag = $strict ? $size > $min && $size < $max : $size >= $min && $size <= $max; 121 | if (!$flag) { 122 | break; 123 | } 124 | } 125 | 126 | return $flag; 127 | } 128 | 129 | /** 130 | * @param $value 131 | * @param $max 132 | * @param bool $strict 133 | * @return bool 134 | */ 135 | public static function maxCount($value, $max, $strict = false): bool 136 | { 137 | $value = self::value($value); 138 | $count = self::getCount($value); 139 | 140 | return $strict ? $count < $max : $count <= $max; 141 | } 142 | 143 | /** 144 | * @param $value 145 | * @param $min 146 | * @param bool $strict 147 | * @return bool 148 | */ 149 | public static function minCount($value, $min, $strict = false): bool 150 | { 151 | $value = self::value($value); 152 | $count = self::getCount($value); 153 | 154 | return $strict ? $count > $min : $count >= $min; 155 | } 156 | 157 | /** 158 | * @param $value 159 | * @param $min 160 | * @param $max 161 | * @return bool 162 | */ 163 | public static function countBetween($value, $min, $max, $strict = false): bool 164 | { 165 | $value = self::value($value); 166 | $count = self::getCount($value); 167 | 168 | return $strict ? $count > $min && $count < $max : $count >= $min && $count <= $max; 169 | } 170 | 171 | /** 172 | * @param $value 173 | * @return bool 174 | */ 175 | protected static function isArray($value): bool 176 | { 177 | return isset($value[0]); 178 | } 179 | 180 | /** 181 | * @param $value 182 | * @return array 183 | */ 184 | protected static function value($value): array 185 | { 186 | $out = []; 187 | $isArray = self::isArray($value); 188 | if (!empty($value) && !$isArray) { 189 | $out = [$value]; 190 | } elseif ($isArray) { 191 | $out = $value; 192 | } 193 | 194 | return $out; 195 | } 196 | 197 | /** 198 | * @param $value 199 | * @return int 200 | */ 201 | protected static function getCount($value): int 202 | { 203 | $count = 0; 204 | foreach ($value as $file) { 205 | if (!$file['error'] && is_uploaded_file($file['tmp_name'])) { 206 | $count++; 207 | } 208 | } 209 | 210 | return $count; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/Filters.php: -------------------------------------------------------------------------------- 1 | setGpcSeed(); 18 | $this->fields = $fields; 19 | } 20 | 21 | /** 22 | * @return string 23 | */ 24 | private function setGpcSeed () 25 | { 26 | $this->gpc_seed = 'sanitize_seed_' . base_convert(md5(realpath(MODX_MANAGER_PATH . 'includes/protect.inc.php')), 27 | 16, 36); 28 | 29 | return; 30 | } 31 | 32 | /** 33 | * Remove fucking modX_sanitize_gpc 34 | * 35 | * @param $target 36 | * @param int $count 37 | * @return mixed 38 | */ 39 | public function removeGpc (&$target, $count = 0) 40 | { 41 | if (empty($this->gpc_seed) || empty($this->fields)) return; 42 | 43 | foreach ($target as $key => $value) { 44 | if (!in_array($key, $this->fields)) { 45 | continue; 46 | } 47 | if (is_array($value)) { 48 | $count++; 49 | if (10 < $count) { 50 | break; 51 | } 52 | $this->removeGpc($value, $count); 53 | $count--; 54 | } else { 55 | $value = str_replace($this->gpc_seed, '', $value); 56 | $value = str_replace('sanitized_by_modxfields; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/Lexicon.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Batch 12 | { 13 | private $MailChimp; 14 | 15 | private $operations = array(); 16 | private $batch_id; 17 | 18 | public function __construct(MailChimp $MailChimp, $batch_id=null) 19 | { 20 | $this->MailChimp = $MailChimp; 21 | $this->batch_id = $batch_id; 22 | } 23 | 24 | /** 25 | * Add an HTTP DELETE request operation to the batch - for deleting data 26 | * @param string $id ID for the operation within the batch 27 | * @param string $method URL of the API request method 28 | * @return void 29 | */ 30 | public function delete($id, $method) 31 | { 32 | $this->queueOperation('DELETE', $id, $method); 33 | } 34 | 35 | /** 36 | * Add an HTTP GET request operation to the batch - for retrieving data 37 | * @param string $id ID for the operation within the batch 38 | * @param string $method URL of the API request method 39 | * @param array $args Assoc array of arguments (usually your data) 40 | * @return void 41 | */ 42 | public function get($id, $method, $args=array()) 43 | { 44 | $this->queueOperation('GET', $id, $method, $args); 45 | } 46 | 47 | /** 48 | * Add an HTTP PATCH request operation to the batch - for performing partial updates 49 | * @param string $id ID for the operation within the batch 50 | * @param string $method URL of the API request method 51 | * @param array $args Assoc array of arguments (usually your data) 52 | * @return void 53 | */ 54 | public function patch($id, $method, $args=array()) 55 | { 56 | $this->queueOperation('PATCH', $id, $method, $args); 57 | } 58 | 59 | /** 60 | * Add an HTTP POST request operation to the batch - for creating and updating items 61 | * @param string $id ID for the operation within the batch 62 | * @param string $method URL of the API request method 63 | * @param array $args Assoc array of arguments (usually your data) 64 | * @return void 65 | */ 66 | public function post($id, $method, $args=array()) 67 | { 68 | $this->queueOperation('POST', $id, $method, $args); 69 | } 70 | 71 | /** 72 | * Add an HTTP PUT request operation to the batch - for creating new items 73 | * @param string $id ID for the operation within the batch 74 | * @param string $method URL of the API request method 75 | * @param array $args Assoc array of arguments (usually your data) 76 | * @return void 77 | */ 78 | public function put($id, $method, $args=array()) 79 | { 80 | $this->queueOperation('PUT', $id, $method, $args); 81 | } 82 | 83 | /** 84 | * Execute the batch request 85 | * @param int $timeout Request timeout in seconds (optional) 86 | * @return array|false Assoc array of API response, decoded from JSON 87 | */ 88 | public function execute($timeout=10) 89 | { 90 | $req = array('operations' => $this->operations); 91 | 92 | $result = $this->MailChimp->post('batches', $req, $timeout); 93 | 94 | if ($result && isset($result['id'])) { 95 | $this->batch_id = $result['id']; 96 | } 97 | 98 | return $result; 99 | } 100 | 101 | /** 102 | * Check the status of a batch request. If the current instance of the Batch object 103 | * was used to make the request, the batch_id is already known and is therefore optional. 104 | * @param string $batch_id ID of the batch about which to enquire 105 | * @return array|false Assoc array of API response, decoded from JSON 106 | */ 107 | public function checkStatus($batch_id=null) 108 | { 109 | if ($batch_id===null && $this->batch_id) $batch_id = $this->batch_id; 110 | return $this->MailChimp->get('batches/'.$batch_id); 111 | } 112 | 113 | /** 114 | * Add an operation to the internal queue. 115 | * @param string $http_verb GET, POST, PUT, PATCH or DELETE 116 | * @param string $id ID for the operation within the batch 117 | * @param string $method URL of the API request method 118 | * @param array $args Assoc array of arguments (usually your data) 119 | * @return void 120 | */ 121 | private function queueOperation($http_verb, $id, $method, $args=null) 122 | { 123 | $operation = array( 124 | 'operation_id' => $id, 125 | 'method' => $http_verb, 126 | 'path' => $method, 127 | ); 128 | 129 | if ($args) { 130 | $key = ($http_verb == 'GET' ? 'params' : 'body'); 131 | $operation[$key] = json_encode($args); 132 | } 133 | 134 | $this->operations[] = $operation; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/MailChimp/MailChimp.php: -------------------------------------------------------------------------------- 1 | 9 | * @version 2.1 10 | */ 11 | class MailChimp 12 | { 13 | private $api_key; 14 | private $api_endpoint = 'https://.api.mailchimp.com/3.0'; 15 | 16 | /* SSL Verification 17 | Read before disabling: 18 | http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/ 19 | */ 20 | public $verify_ssl = true; 21 | 22 | private $last_error = ''; 23 | private $last_response = array(); 24 | private $last_request = array(); 25 | 26 | /** 27 | * Create a new instance 28 | * @param string $api_key Your MailChimp API key 29 | */ 30 | public function __construct($api_key) 31 | { 32 | $this->api_key = $api_key; 33 | 34 | list(, $datacentre) = explode('-', $this->api_key); 35 | $this->api_endpoint = str_replace('', $datacentre, $this->api_endpoint); 36 | 37 | $this->last_response = array('headers'=>null, 'body'=>null); 38 | } 39 | 40 | /** 41 | * Create a new instance of a Batch request. Optionally with the ID of an existing batch. 42 | * @param string $batch_id Optional ID of an existing batch, if you need to check its status for example. 43 | * @return Batch New Batch object. 44 | */ 45 | public function newBatch($batch_id=null) 46 | { 47 | return new Batch($this, $batch_id); 48 | } 49 | 50 | /** 51 | * Convert an email address into a 'subscriber hash' for identifying the subscriber in a method URL 52 | * @param string $email The subscriber's email address 53 | * @return string Hashed version of the input 54 | */ 55 | public function getSubscriberHash($email) 56 | { 57 | return md5(strtolower($email)); 58 | } 59 | 60 | /** 61 | * Get the last error returned by either the network transport, or by the API. 62 | * If something didn't work, this should contain the string describing the problem. 63 | * @return array|false describing the error 64 | */ 65 | public function getLastError() 66 | { 67 | if ($this->last_error) return $this->last_error; 68 | return false; 69 | } 70 | 71 | /** 72 | * Get an array containing the HTTP headers and the body of the API response. 73 | * @return array Assoc array with keys 'headers' and 'body' 74 | */ 75 | public function getLastResponse() 76 | { 77 | return $this->last_response; 78 | } 79 | 80 | /** 81 | * Get an array containing the HTTP headers and the body of the API request. 82 | * @return array Assoc array 83 | */ 84 | public function getLastRequest() 85 | { 86 | return $this->last_request; 87 | } 88 | 89 | /** 90 | * Make an HTTP DELETE request - for deleting data 91 | * @param string $method URL of the API request method 92 | * @param array $args Assoc array of arguments (if any) 93 | * @param int $timeout Timeout limit for request in seconds 94 | * @return array|false Assoc array of API response, decoded from JSON 95 | */ 96 | public function delete($method, $args=array(), $timeout=10) 97 | { 98 | return $this->makeRequest('delete', $method, $args, $timeout); 99 | } 100 | 101 | /** 102 | * Make an HTTP GET request - for retrieving data 103 | * @param string $method URL of the API request method 104 | * @param array $args Assoc array of arguments (usually your data) 105 | * @param int $timeout Timeout limit for request in seconds 106 | * @return array|false Assoc array of API response, decoded from JSON 107 | */ 108 | public function get($method, $args=array(), $timeout=10) 109 | { 110 | return $this->makeRequest('get', $method, $args, $timeout); 111 | } 112 | 113 | /** 114 | * Make an HTTP PATCH request - for performing partial updates 115 | * @param string $method URL of the API request method 116 | * @param array $args Assoc array of arguments (usually your data) 117 | * @param int $timeout Timeout limit for request in seconds 118 | * @return array|false Assoc array of API response, decoded from JSON 119 | */ 120 | public function patch($method, $args=array(), $timeout=10) 121 | { 122 | return $this->makeRequest('patch', $method, $args, $timeout); 123 | } 124 | 125 | /** 126 | * Make an HTTP POST request - for creating and updating items 127 | * @param string $method URL of the API request method 128 | * @param array $args Assoc array of arguments (usually your data) 129 | * @param int $timeout Timeout limit for request in seconds 130 | * @return array|false Assoc array of API response, decoded from JSON 131 | */ 132 | public function post($method, $args=array(), $timeout=10) 133 | { 134 | return $this->makeRequest('post', $method, $args, $timeout); 135 | } 136 | 137 | /** 138 | * Make an HTTP PUT request - for creating new items 139 | * @param string $method URL of the API request method 140 | * @param array $args Assoc array of arguments (usually your data) 141 | * @param int $timeout Timeout limit for request in seconds 142 | * @return array|false Assoc array of API response, decoded from JSON 143 | */ 144 | public function put($method, $args=array(), $timeout=10) 145 | { 146 | return $this->makeRequest('put', $method, $args, $timeout); 147 | } 148 | 149 | /** 150 | * Performs the underlying HTTP request. Not very exciting. 151 | * @param string $http_verb The HTTP verb to use: get, post, put, patch, delete 152 | * @param string $method The API method to be called 153 | * @param array $args Assoc array of parameters to be passed 154 | * @return array|false Assoc array of decoded result 155 | */ 156 | private function makeRequest($http_verb, $method, $args=array(), $timeout=10) 157 | { 158 | if (!function_exists('curl_init') || !function_exists('curl_setopt')) { 159 | throw new \Exception("cURL support is required, but can't be found."); 160 | } 161 | 162 | $url = $this->api_endpoint.'/'.$method; 163 | 164 | $this->last_error = ''; 165 | $response = array('headers'=>null, 'body'=>null); 166 | $this->last_response = $response; 167 | 168 | $this->last_request = array( 169 | 'method' => $http_verb, 170 | 'path' => $method, 171 | 'url' => $url, 172 | 'body' => '', 173 | 'timeout'=> $timeout, 174 | ); 175 | 176 | $ch = curl_init(); 177 | curl_setopt($ch, CURLOPT_URL, $url); 178 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/vnd.api+json', 179 | 'Content-Type: application/vnd.api+json', 180 | 'Authorization: apikey '.$this->api_key)); 181 | curl_setopt($ch, CURLOPT_USERAGENT, 'DrewM/MailChimp-API/3.0 (github.com/drewm/mailchimp-api)'); 182 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 183 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 184 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl); 185 | curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 186 | curl_setopt($ch, CURLOPT_ENCODING, ''); 187 | curl_setopt($ch, CURLINFO_HEADER_OUT, true); 188 | 189 | switch($http_verb) { 190 | case 'post': 191 | curl_setopt($ch, CURLOPT_POST, true); 192 | $this->attachRequestPayload($ch, $args); 193 | break; 194 | 195 | case 'get': 196 | $query = http_build_query($args); 197 | curl_setopt($ch, CURLOPT_URL, $url.'?'.$query); 198 | break; 199 | 200 | case 'delete': 201 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); 202 | break; 203 | 204 | case 'patch': 205 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH'); 206 | $this->attachRequestPayload($ch, $args); 207 | break; 208 | 209 | case 'put': 210 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); 211 | $this->attachRequestPayload($ch, $args); 212 | break; 213 | } 214 | 215 | $response['body'] = curl_exec($ch); 216 | $response['headers'] = curl_getinfo($ch); 217 | 218 | $this->last_request['headers'] = $response['headers']['request_header']; 219 | 220 | if ($response['body'] === false) { 221 | $this->last_error = curl_error($ch); 222 | } 223 | 224 | curl_close($ch); 225 | 226 | return $this->formatResponse($response); 227 | } 228 | 229 | /** 230 | * Encode the data and attach it to the request 231 | * @param resource $ch cURL session handle, used by reference 232 | * @param array $data Assoc array of data to attach 233 | */ 234 | private function attachRequestPayload(&$ch, $data) 235 | { 236 | $encoded = json_encode($data); 237 | $this->last_request['body'] = $encoded; 238 | curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded); 239 | } 240 | 241 | /** 242 | * Decode the response and format any error messages for debugging 243 | * @param array $response The response from the curl request 244 | * @return array|false The JSON decoded into an array 245 | */ 246 | private function formatResponse($response) 247 | { 248 | $this->last_response = $response; 249 | 250 | if (!empty($response['body'])) { 251 | 252 | $d = json_decode($response['body'], true); 253 | 254 | if (isset($d['status']) && $d['status']!='200' && isset($d['detail'])) { 255 | $this->last_error = sprintf('%d: %s', $d['status'], $d['detail']); 256 | } 257 | 258 | return $d; 259 | } 260 | 261 | return false; 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/SubmitProtection.php: -------------------------------------------------------------------------------- 1 | isSubmitted() && $this->getCFGDef('protectSubmit', 1)) { 23 | $formId = $this->getFormId(); 24 | $hash = $this->getFormHash(); 25 | if (isset($_SESSION[$formId . '_hash']) 26 | && $_SESSION[$formId . '_hash'] == $hash 27 | && $hash != '') { 28 | $result = true; 29 | $this->addMessage($this->translate('form.protectSubmit')); 30 | $this->log('Submit protection enabled'); 31 | } 32 | } 33 | 34 | return $result; 35 | } 36 | 37 | /** 38 | * Проверка повторной отправки в течение определенного времени, в секундах 39 | * @return bool если защита сработала, то true 40 | */ 41 | public function checkSubmitLimit() 42 | { 43 | $submitLimit = $this->getCFGDef('submitLimit', 60); 44 | $result = false; 45 | $formId = $this->getFormId(); 46 | if (isset($_SESSION[$formId . '_limit']) && $this->isSubmitted() && $submitLimit > 0) { 47 | if (time() < $submitLimit + $_SESSION[$formId . '_limit']) { 48 | $result = true; 49 | $this->addMessage($this->translate('form.submitLimit') . 50 | ($submitLimit >= 60 51 | ? round($submitLimit / 60, 0) . ' ' . $this->translate('form.minutes') . '.' 52 | : $submitLimit . ' ' . $this->translate('form.seconds') . '.' 53 | )); 54 | $this->log('Submit limit enabled'); 55 | } else { 56 | unset($_SESSION[$formId . '_limit']); 57 | } //time expired 58 | } 59 | 60 | return $result; 61 | } 62 | 63 | /** 64 | * @return $this 65 | */ 66 | public function setSubmitProtection() 67 | { 68 | $formId = $this->getFormId(); 69 | if ($this->getCFGDef('protectSubmit', 1)) { 70 | $_SESSION[$formId . '_hash'] = $this->getFormHash(); 71 | } //hash is set earlier 72 | if ($this->getCFGDef('submitLimit', 60) > 0) { 73 | $_SESSION[$formId . '_limit'] = time(); 74 | } 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * @return array|string 81 | */ 82 | public function getFormHash() 83 | { 84 | $hash = []; 85 | $protectSubmit = $this->getCFGDef('protectSubmit', 1); 86 | if (!is_numeric($protectSubmit)) { //supplied field names 87 | $protectSubmit = $this->config->loadArray($protectSubmit); 88 | foreach ($protectSubmit as $field) { 89 | $hash[] = $this->getField(trim($field)); 90 | } 91 | } else //all required fields 92 | { 93 | $rules = $this->getValidationRules(); 94 | foreach (array_keys($rules) as $field) { 95 | if (isset($rules[$field]['required'])) { 96 | $hash[] = $this->getField($field); 97 | } 98 | } 99 | if (empty($hash)) { 100 | $this->log('No rules found to run submit protection'); 101 | } 102 | } 103 | if ($hash) { 104 | $hash = md5(jsonHelper::toJSON($hash)); 105 | } 106 | 107 | return $hash; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/Validator.php: -------------------------------------------------------------------------------- 1 | format($format) == $value; 30 | } 31 | 32 | /** 33 | * @param $value 34 | * @param $min 35 | * @return bool 36 | */ 37 | public static function min($value, $min): bool 38 | { 39 | return is_scalar($value) && $value >= $min; 40 | } 41 | 42 | /** 43 | * @param $value 44 | * @param $max 45 | * @return bool 46 | */ 47 | public static function max($value, $max): bool 48 | { 49 | return is_scalar($value) && $value <= $max; 50 | } 51 | 52 | /** 53 | * @param $value 54 | * @param $min 55 | * @return bool 56 | */ 57 | public static function greater($value, $min): bool 58 | { 59 | return is_scalar($value) && $value > $min; 60 | } 61 | 62 | /** 63 | * @param $value 64 | * @param $max 65 | * @return bool 66 | */ 67 | public static function less($value, $max): bool 68 | { 69 | return is_scalar($value) && $value < $max; 70 | } 71 | 72 | /** 73 | * @param $value 74 | * @param $min 75 | * @param $max 76 | * @param bool $strict 77 | * @return bool 78 | */ 79 | public static function between($value, $min, $max, $strict = false): bool 80 | { 81 | return (is_scalar($value) && ($strict ? $value > $min && $value < $max : $value >= $min && $value <= $max)); 82 | } 83 | 84 | /** 85 | * @param $value 86 | * @param $allowed 87 | * @return bool 88 | */ 89 | public static function equals($value, $allowed): bool 90 | { 91 | return is_scalar($value) && $value === $allowed; 92 | } 93 | 94 | /** 95 | * @param $value 96 | * @param array $allowed 97 | * @return bool 98 | */ 99 | public static function in($value, $allowed): bool 100 | { 101 | return is_scalar($value) && in_array($value, $allowed, true); 102 | } 103 | 104 | /** 105 | * @param $value 106 | * @return bool 107 | */ 108 | public static function alpha($value): bool 109 | { 110 | return (bool) is_scalar($value) && preg_match('/^\pL++$/uD', $value); 111 | } 112 | 113 | /** 114 | * @param $value 115 | * @return bool 116 | */ 117 | public static function numeric($value): bool 118 | { 119 | return (bool) is_scalar($value) && preg_match('/^[0-9]+$/', $value); 120 | } 121 | 122 | /** 123 | * @param $value 124 | * @return bool 125 | */ 126 | public static function alphaNumeric($value): bool 127 | { 128 | return (bool) is_scalar($value) && preg_match('/^[\pL\pN]++$/uD', $value); 129 | } 130 | 131 | /** 132 | * @param $value 133 | * @return bool 134 | */ 135 | public static function slug($value): bool 136 | { 137 | return (bool) is_scalar($value) && preg_match('/^[\pL\pN\-\_]++$/uD', $value); 138 | } 139 | 140 | /** 141 | * @param $value 142 | * @return bool 143 | */ 144 | public static function decimal($value): bool 145 | { 146 | return (bool) is_scalar($value) && preg_match('/^[0-9]+(?:\.[0-9]+)?$/D', $value); 147 | } 148 | 149 | 150 | /** 151 | * @param $value 152 | * @return bool 153 | */ 154 | public static function phone($value): bool 155 | { 156 | return (bool) is_scalar($value) && preg_match('#^[0-9\(\)\+ \-]+$#', $value); 157 | } 158 | 159 | /** 160 | * @param $value 161 | * @param $regexp 162 | * @return bool 163 | */ 164 | public static function matches($value, $regexp): bool 165 | { 166 | return (bool) is_scalar($value) && preg_match($regexp, $value); 167 | } 168 | 169 | /** 170 | * @param $value 171 | * @return bool 172 | */ 173 | public static function url($value): bool 174 | { 175 | return (bool) is_scalar($value) && preg_match( 176 | '~^ 177 | [-a-z0-9+.]++:// 178 | (?!-)[-a-z0-9]{1,63}+(? $minLength : $length >= $minLength; 223 | } 224 | 225 | /** 226 | * @param $value 227 | * @param $maxLength 228 | * @param bool $strict 229 | * @return bool 230 | */ 231 | public static function maxLength($value, $maxLength, $strict = false): bool 232 | { 233 | if (!is_scalar($value)) { 234 | return false; 235 | } 236 | $length = self::getLength($value); 237 | 238 | return $strict ? $length < $maxLength : $length <= $maxLength; 239 | } 240 | 241 | /** 242 | * @param $value 243 | * @param $minLength 244 | * @param $maxLength 245 | * @param bool $strict 246 | * @return bool 247 | */ 248 | public static function lengthBetween($value, $minLength, $maxLength, $strict = false): bool 249 | { 250 | if (!is_scalar($value)) { 251 | return false; 252 | } 253 | $length = self::getLength($value); 254 | 255 | return $strict ? $length > $minLength && $length < $maxLength : $length >= $minLength && $length <= $maxLength; 256 | } 257 | 258 | /** 259 | * @param $value 260 | * @param $minSize 261 | * @param bool $strict 262 | * @return bool 263 | */ 264 | public static function minCount($value, $minSize, $strict = false): bool 265 | { 266 | if (!is_array($value)) { 267 | return false; 268 | } 269 | $count = count($value); 270 | 271 | return $strict ? $count > $minSize : $count >= $minSize; 272 | } 273 | 274 | /** 275 | * @param $value 276 | * @param $maxSize 277 | * @param bool $strict 278 | * @return bool 279 | */ 280 | public static function maxCount($value, $maxSize, $strict = false): bool 281 | { 282 | if (!is_array($value)) { 283 | return false; 284 | } 285 | $count = count($value); 286 | 287 | return $strict ? $count < $maxSize : $count <= $maxSize; 288 | } 289 | 290 | /** 291 | * @param $value 292 | * @param $minSize 293 | * @param $maxSize 294 | * @param bool $strict 295 | * @return bool 296 | */ 297 | public static function countBetween($value, $minSize, $maxSize, $strict = false): bool 298 | { 299 | if (!is_array($value)) { 300 | return false; 301 | } 302 | $count = count($value); 303 | 304 | return $strict ? $count > $minSize && $count < $maxSize : $count >= $minSize && $count <= $maxSize; 305 | } 306 | 307 | /** 308 | * @param $string 309 | * @return int 310 | */ 311 | protected static function getLength($string) 312 | { 313 | return mb_strlen($string); 314 | } 315 | 316 | /** 317 | * @param $email 318 | * @return string 319 | */ 320 | protected static function sanitizeEmail($email) 321 | { 322 | if (function_exists('idn_to_ascii')) { 323 | $_email = explode('@', $email); 324 | $_email[1] = $_email[1] ?? ''; 325 | if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46')) { 326 | $_email[1] = idn_to_ascii($_email[1], IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46); 327 | } else { 328 | $_email[1] = idn_to_ascii($_email[1]); 329 | } 330 | $email = implode('@', $_email); 331 | } 332 | 333 | return $email; 334 | } 335 | } 336 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/Captcha.php: -------------------------------------------------------------------------------- 1 | db->connect(); 6 | if (empty ($modx->config)) { 7 | $modx->getSettings(); 8 | } 9 | if(strstr($_SERVER['HTTP_REFERER'],$modx->getConfig('site_url')) === false || !isset($_REQUEST['formid'])) throw new Exception('Wrong captcha request'); 10 | $formid = (string) $_REQUEST['formid']; 11 | include_once ('modxCaptcha.php'); 12 | $width = isset($_REQUEST['w']) ? (int) $_REQUEST['w'] : 200; 13 | $height = isset($_REQUEST['h']) ? (int) $_REQUEST['h'] : 160; 14 | $captcha = new ModxCaptcha($modx, $width, $height); 15 | $_SESSION[$formid.'.captcha'] = $captcha->word; 16 | $captcha->outputImage(); 17 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/modxCaptcha.php: -------------------------------------------------------------------------------- 1 | modx = $modx; 31 | $this->dir_font = __DIR__ . $this->dir_font; 32 | $this->dir_noise = __DIR__ . $this->dir_noise; 33 | $this->im_width = $width; 34 | $this->im_height = $height; 35 | $this->word = $this->pickWord(); 36 | } 37 | 38 | /** 39 | * @param bool $inline 40 | * @return string 41 | */ 42 | public function outputImage($inline = false) 43 | { 44 | /* output the image as jpeg */ 45 | $this->drawImage(); 46 | ob_clean(); 47 | if ($inline) { 48 | ob_start(); 49 | imagejpeg($this->im); 50 | $image = ob_get_contents(); 51 | ob_end_clean(); 52 | 53 | return 'data:image/jpeg;base64,' . base64_encode($image); 54 | } 55 | header("Content-type: image/jpeg"); 56 | imagejpeg($this->im); 57 | imagedestroy($this->im); 58 | } 59 | 60 | /** 61 | * @return string 62 | */ 63 | public function pickWord() 64 | { 65 | // set default words 66 | $words = "MODX,Access,Better,BitCode,Chunk,Cache,Desc,Design,Excell,Enjoy,URLs,TechView,Gerald,Griff,Humphrey,Holiday,Intel,Integration,Joystick,Join(),Oscope,Genetic,Light,Likeness,Marit,Maaike,Niche,Netherlands,Ordinance,Oscillo,Parser,Phusion,Query,Question,Regalia,Righteous,Snippet,Sentinel,Template,Thespian,Unity,Enterprise,Verily,Veri,Website,WideWeb,Yap,Yellow,Zebra,Zygote"; 67 | $words = $this->modx->getConfig('captcha_words') ? $this->modx->getConfig('captcha_words') : $words; 68 | $words = str_replace(array(' ', ',,'), array('', ','), $words); 69 | $arr_words = explode(',', $words); 70 | 71 | /* pick one randomly for text verification */ 72 | 73 | return (string)$arr_words[array_rand($arr_words)] . rand(10, 999); 74 | } 75 | 76 | /** 77 | * @return resource 78 | */ 79 | private function drawText() 80 | { 81 | $dir = dir($this->dir_font); 82 | $fontstmp = array(); 83 | while (false !== ($file = $dir->read())) { 84 | if (substr($file, -4) == '.ttf') { 85 | $fontstmp[] = $this->dir_font . $file; 86 | } 87 | } 88 | $dir->close(); 89 | $text_font = (string)$fontstmp[array_rand($fontstmp)]; 90 | $chars = mb_str_split($this->word); 91 | $_chars = array(); 92 | $maxWidth = $this->im_width / count($chars); 93 | $text_size = round(max($maxWidth, $this->im_height) * 3 /4.5 ); 94 | $maxHeight = 0; 95 | $totalWidth = 0; 96 | foreach ($chars as $index => $value) { 97 | $text_angle = rand(-20, 20); 98 | $size = $text_size; 99 | $box = imagettfbbox($size, $text_angle, $text_font, $value); 100 | $charWidth = $box[2] - $box[0]; 101 | $charHeight = abs($box[5] - $box[3]); 102 | $_chars[] = array( 103 | 'angle' => $text_angle, 104 | 'size' => $size, 105 | 'width' => $charWidth, 106 | 'height' => $charHeight 107 | ); 108 | if ($charHeight > $maxHeight) $maxHeight = $charHeight; 109 | $totalWidth += $charWidth; 110 | } 111 | 112 | $minRatio = min(1, $this->im_width / $totalWidth, $this->im_height / $maxHeight); 113 | $size = round($text_size * $minRatio * 0.9); 114 | 115 | $totalWidth = 0; 116 | foreach ($_chars as $index => &$data) { 117 | $data['size'] = $size; 118 | $box = imagettfbbox($data['size'], $data['angle'], $text_font, $chars[$index]); 119 | $charWidth = $box[2] - $box[0]; 120 | $charHeight = abs($box[5] - $box[3]); 121 | $data['width'] = $charWidth; 122 | $data['height'] = $charHeight; 123 | $totalWidth += $charWidth; 124 | } 125 | /* create canvas for text drawing */ 126 | $im_text = imagecreate($this->im_width, $this->im_height); 127 | $bg_color = imagecolorallocate($im_text, 255, 255, 255); 128 | $text_x = ($this->im_width - $totalWidth) / 2; 129 | foreach ($_chars as $index => $data) { 130 | /* calculate center position of text */ 131 | $text_y = ($this->im_height + $data['height'])/2; 132 | /* pick color for text */ 133 | $text_color = imagecolorallocate($im_text, rand(10, 200), rand(10, 200), rand(10, 200)); 134 | 135 | /* draw text into canvas */ 136 | imagettftext( 137 | $im_text, 138 | $data['size'], 139 | $data['angle'], 140 | (int)$text_x, 141 | (int)$text_y, 142 | $text_color, 143 | $text_font, 144 | $chars[$index]); 145 | $text_x += $data['width']; 146 | } 147 | /* remove background color */ 148 | imagecolortransparent($im_text, $bg_color); 149 | 150 | return $im_text; 151 | } 152 | 153 | 154 | /** 155 | * @return null|resource 156 | */ 157 | private function drawImage() 158 | { 159 | 160 | /* pick one background image randomly from image directory */ 161 | $img_file = $this->dir_noise . "noise" . rand(1, 4) . ".jpg"; 162 | 163 | /* create "noise" background image from your image stock*/ 164 | 165 | $noise_img = imagecreatefromjpeg($img_file); 166 | $noise_width = imagesx($noise_img); 167 | $noise_height = imagesy($noise_img); 168 | 169 | /* resize the background image to fit the size of image output */ 170 | $this->im = imagecreatetruecolor($this->im_width, $this->im_height); 171 | imagecopyresampled( 172 | $this->im, 173 | $noise_img, 174 | 0, 0, 0, 0, 175 | $this->im_width, 176 | $this->im_height, 177 | $noise_width, 178 | $noise_height 179 | ); 180 | 181 | /* put text image into background image */ 182 | imagecopymerge( 183 | $this->im, 184 | $this->drawText(), 185 | 0, 0, 0, 0, 186 | $this->im_width, 187 | $this->im_height, 188 | 70 189 | ); 190 | 191 | return $this->im; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/index.html: -------------------------------------------------------------------------------- 1 |

Unauthorized access

2 | You're not allowed to access file folder -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pathologic/FormLister/4fc2258f57a9c6286b2abd86da00738407b19f77/assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise1.jpg -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pathologic/FormLister/4fc2258f57a9c6286b2abd86da00738407b19f77/assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise2.jpg -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pathologic/FormLister/4fc2258f57a9c6286b2abd86da00738407b19f77/assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise3.jpg -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pathologic/FormLister/4fc2258f57a9c6286b2abd86da00738407b19f77/assets/snippets/FormLister/lib/captcha/modxCaptcha/noises/noise4.jpg -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/ttf/ftb_____.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pathologic/FormLister/4fc2258f57a9c6286b2abd86da00738407b19f77/assets/snippets/FormLister/lib/captcha/modxCaptcha/ttf/ftb_____.ttf -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/modxCaptcha/wrapper.php: -------------------------------------------------------------------------------- 1 | cfg = $cfg; 33 | $this->captcha = new \ModxCaptcha($modx, \APIhelpers::getkey($this->cfg, 'width', 100), 34 | \APIhelpers::getkey($this->cfg, 'height', 60)); 35 | } 36 | 37 | /** 38 | * Устанавливает значение капчи 39 | * @return mixed 40 | */ 41 | public function init() 42 | { 43 | $formid = \APIhelpers::getkey($this->cfg, 'id'); 44 | if ($formid) { 45 | $this->lastValue = isset($_SESSION[$formid . '.captcha']) 46 | ? $_SESSION[$formid . '.captcha'] 47 | : $this->captcha->word; 48 | $_SESSION[$formid . '.captcha'] = $this->captcha->word; 49 | } 50 | } 51 | 52 | /** 53 | * Плейсхолдер капчи для вывода в шаблон 54 | * Может быть ссылкой на коннектор (чтобы можно было обновлять c помощью js), может быть сразу картинкой в base64 55 | * @return string 56 | */ 57 | public function getPlaceholder() 58 | { 59 | $inline = \APIhelpers::getkey($this->cfg, 'inline', 1); 60 | if ($inline) { 61 | $out = $this->captcha->outputImage(true); 62 | } else { 63 | $connectorDir = \APIhelpers::getkey($this->cfg, 'connectorDir', 64 | 'assets/snippets/FormLister/lib/captcha/modxCaptcha/'); 65 | $out = MODX_BASE_URL . $connectorDir . 'connector.php?formid=' . \APIhelpers::getkey($this->cfg, 'id', 66 | 'modx'); 67 | $out .= '&w=' . \APIhelpers::getkey($this->cfg, 'width', 100); 68 | $out .= '&h=' . \APIhelpers::getkey($this->cfg, 'height', 60); 69 | } 70 | 71 | return $out; 72 | } 73 | 74 | /** 75 | * @param \FormLister\Core $FormLister 76 | * @param $value 77 | * @param \FormLister\CaptchaInterface $captcha 78 | * @return bool|string 79 | */ 80 | public static function validate(Core $FormLister, $value, CaptchaInterface $captcha) 81 | { 82 | if (empty($value)) { 83 | $out = \APIhelpers::getkey($captcha->cfg, 'errorEmptyCode', 'Введите проверочный код'); 84 | } else { 85 | $out = strtolower($value) == strtolower($captcha->lastValue) ? true : \APIhelpers::getkey($captcha->cfg, 86 | 'errorCodeFailed', 'Неверный проверочный код'); 87 | } 88 | $FormLister->log('Validate captcha value '.$value.' against '.$captcha->lastValue); 89 | 90 | return $out; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/reCaptcha/wrapper.php: -------------------------------------------------------------------------------- 1 | cfg = $cfg; 26 | $this->modx = $modx; 27 | } 28 | 29 | /** 30 | * Устанавливает значение капчи 31 | * @return mixed 32 | */ 33 | public function init() 34 | { 35 | return; 36 | } 37 | 38 | /** 39 | * Плейсхолдер капчи для вывода в шаблон 40 | * Может быть ссылкой на коннектор (чтобы можно было обновлять c помощью js), может быть сразу картинкой в base64 41 | * @return string 42 | */ 43 | public function getPlaceholder() 44 | { 45 | $siteKey = \APIhelpers::getkey($this->cfg, 'siteKey'); 46 | $reCAPTCHAversion = \APIhelpers::getkey($this->cfg, 'reCAPTCHAversion', "2"); 47 | $classButton = \APIhelpers::getkey($this->cfg, 'classButton', "g-recaptcha"); 48 | $textButton = \APIhelpers::getkey($this->cfg, 'textButton', "Submit"); 49 | $type = \APIhelpers::getkey($this->cfg, 'type', 'image'); 50 | $size = \APIhelpers::getkey($this->cfg, 'size', 'normal'); 51 | $tabindex = \APIhelpers::getkey($this->cfg, 'tabindex', 0); 52 | $theme = \APIhelpers::getkey($this->cfg, 'theme', 'light'); 53 | $id = \APIhelpers::getkey($this->cfg, 'captchaid', \APIhelpers::getkey($this->cfg, 'id')); 54 | $id = 'id="' . $id . '-recaptcha"'; 55 | $badge = \APIhelpers::getkey($this->cfg, 'badge', 'bottomright'); 56 | $callback = \APIhelpers::getkey($this->cfg, 'callback', ''); 57 | $expcallback = \APIhelpers::getkey($this->cfg, 'expired_callback', ''); 58 | $out = ''; 59 | if (!empty($siteKey)) { 60 | switch($reCAPTCHAversion) { 61 | case "3": 62 | $callback = \APIhelpers::getkey($this->cfg, 'callback', 'onSubmit'); 63 | $out = ""; 64 | break; 65 | default: 66 | $out = "
"; 67 | break; 68 | } 69 | } 70 | 71 | return $out; 72 | } 73 | 74 | /** 75 | * @param \FormLister\Core $FormLister 76 | * @param $value 77 | * @param \FormLister\CaptchaInterface $captcha 78 | * @return bool|string 79 | */ 80 | public static function validate(Core $FormLister, $value, CaptchaInterface $captcha) 81 | { 82 | $secretKey = \APIhelpers::getkey($captcha->cfg, 'secretKey'); 83 | $url = "https://www.google.com/recaptcha/api/siteverify?secret=" . $secretKey . "&response=" . $value . "&remoteip=" . \APIhelpers::getUserIP(); 84 | $out = false; 85 | if (!empty($value)) { 86 | $curl = curl_init(); 87 | curl_setopt($curl, CURLOPT_URL, $url); 88 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 89 | curl_setopt($curl, CURLOPT_TIMEOUT, 10); 90 | curl_setopt($curl, CURLOPT_USERAGENT, 91 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16"); 92 | $response = curl_exec($curl); 93 | curl_close($curl); 94 | $response = json_decode($response, true); 95 | $out = $response['success']; 96 | } 97 | if (!$out) { 98 | $out = \APIhelpers::getkey($captcha->cfg, 'errorCodeFailed', 'Вы не прошли проверку'); 99 | } 100 | $FormLister->log('reCaptcha validation result: '.$out); 101 | 102 | return $out; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/smsCaptcha/model.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'phone' => '', 12 | 'code' => '', 13 | 'active' => 0, 14 | 'expires' => 0, 15 | 'ip' => '' 16 | ); 17 | 18 | public function getData($phone,$formid) { 19 | 20 | $this->close(); 21 | $this->markAllEncode(); 22 | $this->newDoc = false; 23 | $result = $this->query("SELECT * from {$this->makeTable($this->table)} where `phone`='{$this->escape($phone)}' AND `formid`='{$this->escape($formid)}'"); 24 | $this->fromArray($this->modx->db->getRow($result)); 25 | $this->store($this->toArray()); 26 | $this->id = $this->eraseField($this->pkName); 27 | if (is_bool($this->id) && $this->id === false) { 28 | $this->id = null; 29 | } else { 30 | $this->decodeFields(); 31 | } 32 | 33 | 34 | return $this; 35 | } 36 | 37 | public function createTable() 38 | { 39 | $table = $this->modx->getFullTableName($this->table); 40 | $q = "CREATE TABLE IF NOT EXISTS {$table} ( 41 | `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, 42 | `formid` VARCHAR(255) NOT NULL DEFAULT '', 43 | `phone` VARCHAR(20) NOT NULL DEFAULT '', 44 | `code` VARCHAR (10) NOT NULL DEFAULT '', 45 | `active` INT(1) NOT NULL DEFAULT 0, 46 | `expires` INT(10) NOT NULL DEFAULT 0, 47 | `ip` VARCHAR (16) NOT NULL DEFAULT '', 48 | KEY `formid` (`formid`), 49 | KEY `phone` (`phone`), 50 | KEY `code` (`code`), 51 | KEY `active` (`active`), 52 | KEY `expires` (`expires`) 53 | ) Engine=MyISAM 54 | "; 55 | $this->modx->db->query($q); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/smsCaptcha/wrapper.php: -------------------------------------------------------------------------------- 1 | cfg = $cfg; 28 | $this->modx = $modx; 29 | } 30 | 31 | /** 32 | * Устанавливает значение капчи 33 | * @return mixed 34 | */ 35 | public function init() 36 | { 37 | return; 38 | } 39 | 40 | /** 41 | * Плейсхолдер капчи для вывода в шаблон 42 | * @return string 43 | */ 44 | public function getPlaceholder() 45 | { 46 | return ''; 47 | } 48 | 49 | /** 50 | * @param \FormLister\Core $FormLister 51 | * @param $value 52 | * @param \FormLister\CaptchaInterface $captcha 53 | * @return bool|string 54 | */ 55 | public static function validate(Core $FormLister, $value, CaptchaInterface $captcha) 56 | { 57 | $id = \APIhelpers::getkey($captcha->cfg, 'id'); 58 | if (empty($value)) { 59 | return \APIhelpers::getkey($captcha->cfg, 'errorEmptyCode', 60 | 'Введите код авторизации'); 61 | } 62 | 63 | if (empty($_SESSION[$id . '.smscaptcha'])) { 64 | return \APIhelpers::getkey($captcha->cfg, 'errorCodeRequired', 65 | 'Получите код авторизации'); 66 | } 67 | 68 | $sms = $FormLister->loadModel('SmsModel'); 69 | 70 | if (is_null($sms->getData($_SESSION[$id . '.smscaptcha'], $id)->getID())) { 71 | 72 | return \APIhelpers::getkey($captcha->cfg, 'errorCodeRequired', 'Получите код авторизации'); 73 | } 74 | 75 | if ($sms->get('code') != $value) { 76 | 77 | return \APIhelpers::getkey($captcha->cfg, 'errorCodeFailed', 'Неверный код авторизации'); 78 | } 79 | 80 | if ($sms->get('expires') < time()) { 81 | $sms->delete($sms->getID()); 82 | 83 | return \APIhelpers::getkey($captcha->cfg, 'errorCodeExpired', 84 | 'Код авторизации истек, получите новый'); 85 | } else { 86 | if (!$sms->get('active')) { 87 | $sms->set('active', 0)->set('expires', time() + \APIhelpers::getkey($captcha->cfg, 'codeLifeTime', 88 | 86400))->set('ip', \APIhelpers::getUserIP())->save(); 89 | } else { 90 | 91 | return \APIhelpers::getkey($captcha->cfg, 'errorCodeUsed', 92 | 'Код авторизации уже использовался'); 93 | } 94 | $out = true; 95 | 96 | $FormLister->setField('captcha.phone', $sms->get('phone')); 97 | } 98 | $FormLister->log('Validate captcha value '.$value.' against '.$sms->get('code')); 99 | 100 | return $out; 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/lib/captcha/yandexCaptcha/wrapper.php: -------------------------------------------------------------------------------- 1 | cfg = $cfg; 26 | $this->modx = $modx; 27 | } 28 | 29 | /** 30 | * Устанавливает значение капчи 31 | * @return mixed 32 | */ 33 | public function init() 34 | { 35 | return; 36 | } 37 | 38 | /** 39 | * Плейсхолдер капчи для вывода в шаблон 40 | * Может быть ссылкой на коннектор (чтобы можно было обновлять c помощью js), может быть сразу картинкой в base64 41 | * @return string 42 | */ 43 | public function getPlaceholder() 44 | { 45 | $siteKey = \APIhelpers::getkey($this->cfg, 'siteKey'); 46 | $id = \APIhelpers::getkey($this->cfg, 'id'); 47 | $id = $id ? ('id="' . $id . '-captcha"') : ''; 48 | $out = ''; 49 | if (!empty($siteKey)) { 50 | $out = "
"; 51 | } 52 | 53 | return $out; 54 | } 55 | 56 | /** 57 | * @param \FormLister\Core $FormLister 58 | * @param $value 59 | * @param \FormLister\CaptchaInterface $captcha 60 | * @return bool|string 61 | */ 62 | public static function validate(Core $FormLister, $value, CaptchaInterface $captcha) 63 | { 64 | $secretKey = \APIhelpers::getkey($captcha->cfg, 'secretKey'); 65 | $params = http_build_query([ 66 | 'secret' => $secretKey, 67 | 'token' => $value, 68 | 'ip' => \APIhelpers::getUserIP() 69 | ]); 70 | $url = "https://smartcaptcha.yandexcloud.net/validate?{$params}"; 71 | $out = false; 72 | if (!empty($value)) { 73 | $curl = curl_init(); 74 | curl_setopt($curl, CURLOPT_URL, $url); 75 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 76 | curl_setopt($curl, CURLOPT_TIMEOUT, 10); 77 | curl_setopt($curl, CURLOPT_USERAGENT, 78 | "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16"); 79 | $response = curl_exec($curl); 80 | curl_close($curl); 81 | $response = json_decode($response, true) ?? []; 82 | $out = isset($response['status']) && $response['status'] === 'ok'; 83 | } 84 | if (!$out) { 85 | $out = \APIhelpers::getkey($captcha->cfg, 'errorCodeFailed', 'Вы не прошли проверку'); 86 | } 87 | $FormLister->log('YandexCaptcha validation result: ' . $out); 88 | 89 | return $out; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/plugin.userHelper.php: -------------------------------------------------------------------------------- 1 | event; 9 | if (!class_exists('\\FormLister\\Core')) { 10 | include_once(MODX_BASE_PATH . 'assets/snippets/FormLister/__autoload.php'); 11 | } 12 | if (($e->name == 'OnWebAuthentication' || $e->name == 'OnUserAuthentication') && isset($userObj)) { 13 | /** 14 | * @var modUsers $userObj 15 | */ 16 | if ($savedpassword != $userObj->getPassword($userpassword)) { 17 | $fails = (int)$userObj->get('failedlogincount'); 18 | $userObj->set('failedlogincount', ++$fails); 19 | if ($fails > $maxFails) { 20 | $userObj->set('blockeduntil', time() + $blockTime); 21 | $userObj->set('failedlogincount', 0); 22 | } 23 | $userObj->save(); 24 | } 25 | } 26 | if (($e->name == 'OnWebLogin' || $e->name == 'OnUserLogin') && isset($userObj)) { 27 | if (!$userObj->get('lastlogin')) { 28 | $userObj->set('lastlogin', time()); 29 | } else { 30 | $userObj->set('lastlogin', $userObj->get('thislogin')); 31 | } 32 | $userObj->set('thislogin', time()); 33 | $userObj->set('logincount', (int)$userObj->get('logincount') + 1); 34 | $userObj->set('failedlogincount', 0); 35 | $userObj->save(false, false); 36 | if (isset($_COOKIE[$cookieName])) { 37 | $userObj->setAutoLoginCookie($cookieName, $cookieLifetime); 38 | } 39 | } 40 | //Updating session_id in cookie, if user is login and just saved 41 | if (($e->name == 'OnWebSaveUser' || $e->name == 'OnUserSave') && isset($userObj)) { 42 | if( (int)$modx->getLoginUserID('web') == (int)$id && isset($_COOKIE[$cookieName]) ) { //checking, if current logined user was saved 43 | $cookieParts = explode("|", $_COOKIE[$cookieName], 4); 44 | if(isset($cookieParts[2]) && ($userObj->get('sessionid') != $cookieParts[2])) { //checking, if session ids in cookie and in user object became not equals 45 | $userObj->setAutoLoginCookie($cookieName, $cookieLifetime); 46 | } 47 | } 48 | } 49 | 50 | if ($e->name == 'OnWebPageInit' || $e->name == 'OnPageNotFound') { 51 | if (function_exists('app')) { 52 | $model = isset($params['model']) && class_exists($params['model']) ? $params['model'] : '\\Pathologic\\EvolutionCMS\\MODxAPI\\modUsers'; 53 | } else { 54 | $model = isset($params['model']) && class_exists($params['model']) ? $params['model'] : '\\modUsers'; 55 | } 56 | $user = new $model($modx); 57 | if ($uid = (int)$modx->getLoginUserID('web')) { 58 | if ($trackWebUserActivity == 'Yes') { 59 | $sid = $modx->sid = session_id(); 60 | $pageId = (int)$modx->documentIdentifier; 61 | $uid = function_exists('app') ? $uid : -1 * $uid; 62 | $name = $modx->db->escape($_SESSION['webShortname'] ?? ''); 63 | $q = $modx->db->query("REPLACE INTO {$modx->getFullTableName('active_users')} (`sid`, `internalKey`, `username`, `lasthit`, `action`, `id`) values('{$sid}', {$uid}, '{$name}', '{$modx->time}', 998, {$pageId})"); 64 | $modx->updateValidatedUserSession(); 65 | } 66 | if (isset($_REQUEST[$logoutKey])) { 67 | $user->logOut($cookieName, true); 68 | $page = $modx->getConfig('site_url') . (isset($_REQUEST['q']) ? $_REQUEST['q'] : ''); 69 | $query = $_GET; 70 | unset($query[$logoutKey], $query['q']); 71 | if ($query) { 72 | $page .= '?' . http_build_query($query); 73 | } 74 | $modx->sendRedirect($page); 75 | } elseif (!$user->edit($uid)->getID() || $user->checkBlock($uid)) { 76 | $user->logOut($cookieName, true); 77 | } 78 | } else { 79 | $user->AutoLogin($cookieLifetime, $cookieName, true); 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /assets/snippets/FormLister/snippet.FormLister.php: -------------------------------------------------------------------------------- 1 | logEvent(0, 1, "Parameter &formid is not set", 'FormLister'); 13 | return; 14 | } 15 | if (!class_exists('\FormLister\Core')) { 16 | include_once('__autoload.php'); 17 | } 18 | $out = ''; 19 | $FLDir = MODX_BASE_PATH . 'assets/snippets/FormLister/'; 20 | if (!isset($controller) || $controller == 'Core') { 21 | $params['controller'] = $controller = "Form"; 22 | } 23 | 24 | $classname = strpos($controller, '\\') === 0 ? $controller : '\\FormLister\\'.$controller; 25 | 26 | if (!class_exists($classname)) { 27 | $dir = isset($dir) ? MODX_BASE_PATH . $dir : $FLDir . "core/controller/"; 28 | if (file_exists($dir . $controller . ".php") && !class_exists($classname)) { 29 | require_once($dir . $controller . ".php"); 30 | } 31 | } 32 | 33 | $DLTemplate = DLTemplate::getInstance($modx); 34 | $templatePath = $DLTemplate->getTemplatePath(); 35 | $templateExtension = $DLTemplate->getTemplateExtension(); 36 | if (class_exists($classname) && is_a($classname, '\\FormLister\\Core', true)) { 37 | /** @var \FormLister\Core $FormLister */ 38 | $FormLister = new $classname($modx, $params); 39 | if (!$FormLister->getFormId()) return; 40 | $FormLister->initForm(); 41 | $out = $FormLister->render(); 42 | if ($FormLister->getFormStatus() && isset($saveObject) && is_scalar($saveObject)) { 43 | $modx->setPlaceholder($saveObject, $FormLister); 44 | } 45 | 46 | if (!is_null($FormLister->debug)) { 47 | $FormLister->debug->saveLog(); 48 | } 49 | } else { 50 | $modx->logEvent(0, 1, "Controller {$classname} is missing", 'FormLister'); 51 | } 52 | $DLTemplate->setTemplatePath($templatePath)->setTemplateExtension($templateExtension); 53 | 54 | return $out; 55 | -------------------------------------------------------------------------------- /install/assets/plugins/userHelper.tpl: -------------------------------------------------------------------------------- 1 | //