Sergio

Members
  • Content count

    367
  • Joined

  • Last visited

  • Days Won

    8

Sergio last won the day on April 21

Sergio had the most liked content!

Community Reputation

494 Excellent

1 Follower

About Sergio

  • Rank
    Sr. Member
  • Birthday 04/13/1979

Profile Information

  • Gender
    Male
  • Location
    Belo Horizonte, Brazil

Recent Profile Visitors

5,241 profile views
  1. Sendy is great if your budget is small AND you need to send emails to a lot of people (10k+). Mailchimp is incredible, but the price for small business is not so good, especially when a dollar is almost 4 times your currency (Brazilian Real) Just keep an eye on your AWS SES reputation dashboard, for complain and bounce rates.
  2. Sergio

    I added the source code on this post:
  3. The module source is below. Example usage: a checkbox on a contact form (using Form Builder) for the user to subscribe. It's used on https://ricardo-vargas.com/contact/ EXAMPLE A method on _hooks.php. If you don't use Form Builder, use this code on your form page. $forms->addHookBefore('FormBuilderProcessor::emailForm', function($event) { $processor = $event->object; if ($processor->formName == 'contact-form') { $formData = $event->arguments(1); $contact_name = $event->sanitizer->text($formData['contact_name']); $contact_name = substr($contact_name, 0, 30); // limit length further $contact_name = $event->sanitizer->emailHeader($contact_name); $contact_email = $event->sanitizer->text($formData['contact_email']); $contact_email = $event->sanitizer->emailHeader($contact_email); $processor->emailFrom = $contact_email; //reply to $processor->emailSubject = 'Message from '.$contact_name; $form = $event->object->getInputfieldsForm(); $subscribe = $form->get('receive_updates'); $list_id = $form->get('sendy_list_id')->attr('value'); // check to see if they subscribed if ($subscribe->attr('checked')) { $success_url = '/contact'; // $fail_url = '/contact?error=1'; $ProcessSendyAPI = wire('modules')->getModule('ProcessSendyAPI'); $ProcessSendyAPI->subscribeInSendy($contact_name, $contact_email, $list_id, $success_url); } } }); MODULE https://gist.github.com/sjardim/2d834ebb0bd66d4da1ac16072f4075cd <?php namespace ProcessWire; class ProcessSendyAPI extends WireData implements Module, ConfigurableModule { public static function getModuleInfo() { return array( 'title' => __('Process Sendy API'), 'summary' => __('Handle API calls to a Sendy installation'), 'author' => 'Sérgio Jardim', 'version' => '001', 'singular' => true, 'autoload' => false, 'icon' => 'envelope' ); } /** * Data as used by the get/set functions * */ protected $data = array(); /** * Default configuration for module * */ static public function getDefaultData() { return array( "sendy_api_key" => '', "sendy_installation_url" => 'http://www.example.com/sendy' ); } /** * Populate the default config data * */ public function __construct() { foreach(self::getDefaultData() as $key => $value) { $this->$key = $value; } } public static function getModuleConfigInputfields(array $data) { $data = array_merge(self::getDefaultData(), $data); $wrapper = new InputfieldWrapper(); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'sendy_api_key'); $f->label = __('Sendy API Key', __FILE__); $f->description = __('Further instructions at https://sendy.co/api', __FILE__); $f->notes = __('Get your key at http://your_sendy_installation/settings.', __FILE__); $f->value = $data['sendy_api_key']; $wrapper->add($f); $f = wire('modules')->get('InputfieldURL'); $f->attr('name', 'sendy_installation_url'); $f->label = __('Sendy instalation URL', __FILE__); $f->description = __('Your Sendy installation URL without a trailing slash', __FILE__); $f->notes = 'http://www.example.com/sendy'; $f->value = $data['sendy_installation_url']; $wrapper->add($f); return $wrapper; } /** * [subscribeUserOrGuest description] * @param [type] $name [description] * @param [type] $email [description] * @param [type] $list_id [description] * @param [type] $success_url [description] * @param [type] $fail_url [description] * @return [type] [description] */ public function subscribeInSendy($name, $email, $list_id, $success_url = null, $fail_url = null) { $api_key = $this->data['sendy_api_key']; $sendy_url = $this->data['sendy_installation_url']; $postdata = http_build_query( array( 'name' => $name, 'email' => $email, 'list' => $list_id, 'boolean' => 'true' //set this to "true" so that you'll get a plain text response ) ); $opts = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata)); $context = stream_context_create($opts); $result = file_get_contents($sendy_url.'/subscribe', false, $context); //check result and redirect if($result) { $this->wire('log')->save("newsletter", 'A new user subscribed to the site mailing list: '.$email); if($success_url) { header("Location: $success_url"); } } else { $this->wire('log')->save("error", 'Error occurred on subscribing '.$email); if($fail_url) { header("Location: $fail_url"); } } } }
  4. Hi @php ! I'd like to recommend to you a free PHP course by Jeffrey Way, the guy behind Laracasts: https://laracasts.com/series/php-for-beginners I think you're going to love it.
  5. Sergio

    I think you can take a look at the CSS "object-fit" rule. See this codepen: https://codepen.io/akb20/pen/EPoPpx
  6. Sergio

    Thank you, Ryan! Keep the excellent work up! Cheers!
  7. Sergio

    Forgot to say, welcome to the forums! ProCache is awesome. And if you were you, I'd take a look at @tpr's Latte module too. It's great!
  8. Sergio

    Yes. Unless I'm utterly wrong. Twig will render PHP files at runtime, and their output in the browser is the same output that's processed by ProCache. ProCache will render static version of the pages in /assets/ProCache-xxxxx/page-name/index.html that will be server by .htaccess rules (or Nginx rules, like I do)
  9. Sergio

    Yes, it will work. I use Latte template language, but it's pretty similar to Twig, and ProCache work flawlessly.
  10. Sergio

    Hi @Lemoratoire, welcome to the forums. You need to change the field settings. So, go to /setup/field/ find the Body field and on the Input tab change you can add some tags to the "Extra allowed content'" field or, for a full control of what HTML tags you can use, you'll need to disable the "ACF" and the "Use HTML Purifier" options. But beware that this opens a security risk if someone else is entering code beside yourself.
  11. Sergio

    @noelboss, this is BEAUTIFUL!! Very easy to understand. I'm eager to play with it and create a front-end using Vuejs and another with Gatsbyjs. Many thanks for this module!!
  12. All of a sudden, with nothing changed on the database or server, a website was getting error when doing a search: Error: Exception: SQLSTATE[HY000]: General error: 23 Out of resources when opening file './your-database-name/pages_parents.MYD' (Errcode: 24 - Too many open files) (in /home/forge/example.com/public/wire/core/PageFinder.php line 413) #0 /home/forge/example.com/public/wire/core/Wire.php(386): ProcessWire\PageFinder->___find(Object(ProcessWire\Selectors), Array) #1 /home/forge/example.com/public/wire/core/WireHooks.php(723): ProcessWire\Wire->_callMethod('___find', Array) #2 /home/forge/example.com/public/wire/core/Wire.php(442): ProcessWire\WireHooks->runHooks(Object(ProcessWire\PageFinder), 'find', Array) #3 /home/forge/example.com/public/wire/core/PagesLoader.php(248): ProcessWire\Wire->__call('find', Array) #4 /home/forge/example.com/public/wire/core/Pages.php(232): ProcessWire\PagesLoader->find('title~=EAP, lim...', Array) #5 /home/forge/example.com/public/wire/core/Wire.php(383): ProcessWire\Pages->___find('title~=EAP, lim...') #6 /home/forge/example.com/public/wire This error message was shown because: you are logged in as a Superuser. Error has been logged. I tried several things, listed in this thread: https://serverfault.com/questions/791729/ubuntu-16-04-server-mysql-open-file-limit-wont-go-higher-than-65536 But for some reason, MySQL was not getting its limit increased, but in the end, the one that did the trick was this: This worked for me on Ubuntu Xenial 16.04: Create the dir /etc/systemd/system/mysql.service.d Put in /etc/systemd/system/mysql.service.d/override.conf: [Service] LimitNOFILE=1024000 Now execute systemctl daemon-reload systemctl restart mysql.service Yes indeed, LimitNOFILE=infinity actually seems to set it to 65536. You can validate the above after starting MySQL by doing: cat /proc/$(pgrep mysql)/limits | grep files
  13. Sergio

    Really impressive, Diogo! Excellent implementation of the design. And cool stuff having the animations settings manageable by the design team. Congratulations to you and the team!!
  14. Sergio

    You can also add class names on the ProcessPageEditImageSelect module options, but unfortunately UiKit lightbox plugin (https://getuikit.com/docs/lightbox) needs a wrapper div , so the code should be something like: <div uk-lightbox> <a href="image.jpg" data-caption="Caption"></a> </div> @Hurme, maybe you can try creating a new module based on@Martijn Geerts's Image Interceptor for this.
  15. Sergio

    server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; root /home/forge/example.com/public; index index.html index.htm index.php; charset utf-8; # ----------------------------------------------------------------------------------------------- # Access Restrictions: Protect ProcessWire system files # ----------------------------------------------------------------------------------------------- # Block access to ProcessWire system files location ~ \.(inc|info|module|sh|sql)$ { deny all; } # Block access to any file or directory that begins with a period location ~ /\. { deny all; } # Block access to protected assets directories location ~ ^/(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) { deny all; } # Block acceess to the /site/install/ directory location ~ ^/(site|site-[^/]+)/install($|/.*$) { deny all; } # Block dirs in /site/assets/ dirs that start with a hyphen location ~ ^/(site|site-[^/]+)/assets.*/-.+/.* { deny all; } # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, and /wire/index.config.php location ~ ^/(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ { deny all; } # Block access to any PHP-based files in /templates-admin/ location ~ ^/(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP or markup files in /site/templates/ location ~ ^/(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP files in /site/assets/ location ~ ^/(site|site-[^/]+)/assets($|/|/.*\.php)$ { deny all; } # Block access to any PHP files in core or core module directories location ~ ^/wire/(core|modules)/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any PHP files in /site/modules/ location ~ ^/(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any software identifying txt files location ~ ^/(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md)$ { deny all; } # Block all http access to the default/uninstalled site-default directory location ~ ^/site-default/ { deny all; } #Amplify dashboard location /nginx_status { stub_status on; allow 127.0.0.1; deny all; } # ----------------------------------------------------------------------------------------------- # If the request is for a static file, then set expires header and disable logging. # Give control to ProcessWire if the requested file or directory is non-existing. # ----------------------------------------------------------------------------------------------- location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|eot|woff|ttf)$ { expires 15d; log_not_found off; access_log off; try_files $uri $uri/ /index.php?it=$uri&$query_string; } # ----------------------------------------------------------------------------------------------- # ProCache Rules # ----------------------------------------------------------------------------------------------- set $cache_uri $request_uri; if ($request_method = POST) { set $cache_uri 'nocache'; } if ($http_cookie ~* "wires_challenge") { set $cache_uri 'nocache'; } if ($http_cookie ~* "persist") { set $cache_uri 'nocache'; } # ----------------------------------------------------------------------------------------------- # This location processes all other requests. If the request is for a file or directory that # physically exists on the server, then load the file. Else give control to ProcessWire. # ----------------------------------------------------------------------------------------------- location / { expires -1; try_files /site/assets/ProCache-b3d534d...d/$cache_uri/index.html $uri $uri/ /index.php?it=$uri&$args; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/example.com-error.log error; error_page 404 /index.php; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_index index.php; include fastcgi_params; } location ~ /\.ht { deny all; } }