Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/10/2017 in all areas

  1. ProcessWire DropboxAPI on GitHub: https://github.com/clipmagic/DropboxAPI This module is a wrapper for Kunal Varma's Dropbox PHP SDK https://github.com/kunalvarma05/dropbox-php-sdk It was created to perform a specific function for a client, ie upload PDF files on a PW website to a specific Dropbox account folder. The PDF files, created using @Wanze's excellent PagesToPdf module using the WirePDF functions, are generated from Formbuilder forms completed by front-end site visitors. Works a treat! There's more that could be done to allow ProcessWire to take advantage of all the features of the SDK, eg downloads, multiple Dropbox accounts, etc. You are welcome to request changes and/or fork the GitHub project to extend the feature set. Enjoy! System requirements PHP 5.6.4 or greater Composer The PHP mbstring extension General information This module enables you to access a single Dropbox (www.dropbox.com) account to upload files from a ProcessWire website. All kudos to (https://github.com/kunalvarma05/dropbox-php-sdk) for the PHP API. First steps Visit (https://www.dropbox.com/developers) and read the documentation. Log into Dropbox and create a new application. It's recommended to limit ProcessWire App access to a specified folder Make a note of the App key, the App secret and the name of the Dropbox folder Installation Download the zip file into your site/modules folder then expand the zip file. Next, login to ProcessWire > go to Modules > click "Refresh". You should see a note that a new module was found. Install the DropboxAPI module. Configure the module with your App key, App secret and your Call Back URL You need to generate a Dropbox access token to enable your site to communicate with the nominated Dropbox account. Dropbox will generate a token for you or you can create a page for the front end of your ProcessWire site with a template to submit the token request to Dropbox, eg: <?php namespace ProcessWire; $drop = $modules->get('DropboxAPI'); if ($input->get->code && $input->get->state) { $code = $sanitizer->text($input->get->code); $state = $sanitizer->text($input->get->state); //Fetch the AccessToken $accessToken = $drop->getAccessToken($code, $state); echo "Copy/paste this code into the module configuration: " . $accessToken; } else { echo "<p><a href='" . $drop->getAuthURL() . "'>Log in with Dropbox</a></p>"; } ?> Once you have entered the token in the module configuration, you can unpublish this page. Usage Read the dropbox-php-sdk documentation! An example template for sending a file to a Dropbox App folder from ProcessWire: <?php namespace ProcessWire; use Kunnu\Dropbox\Dropbox; use Kunnu\Dropbox\DropboxApp; use Kunnu\Dropbox\DropboxFile; // send pdf to Dropbox $drop = $modules->get('DropboxAPI'); $app = new DropboxApp($drop->app_key, $drop->app_secret, $drop->authorization_code); if ($app) { //Configure Dropbox service $dropbox = new Dropbox($app); $dropboxFile = new DropboxFile('/path/to/myfilename.pdf'); $file = $dropbox->upload($dropboxFile, "/myfilename.pdf", ['autorename' => true]); //Uploaded File meta data if ($file) { $success = $file->getName() . " uploaded to Dropbox"; $drop->log($success); } }
    8 points
  2. And I was sure YOU will ask that ! Sure, I am already trying to get back my Gitlab server. The server was hosted in a VMware guest machine, and when plugged the hdd and put the virtual machine ON, the network simply does not work anymore. Can't ping anything, but I know how to fix it, i am just too lazy those days. Edit: Just to say, I still have the code and used the module in the last days, but it look like its not the Windows compatible version..
    4 points
  3. Hi PW fanatics In this post I share two of my addHookMethods for those interested. As you surely already know (if not, time to take a look at it) the Wire::addHookMethod() and the Wire::addHookProperty() API methods can be used to "breath some extra OOP" into your projects. Using addHookMethods and addHookProperty are alternatives to "Using custom page types in ProcessWire". The methods I want to share: basically the idea here is to get the URL pointing to images uploaded in the admin without writing much code in the template files. With methods like these below, it does not matter what Formatted value is set to the images, because some predefined defaults are used in all circumstances. #1 Example template file code: <?php $img_src = $latest_article->siteFeaturedImage(); ?> <img src="<?= $img_src ?>" alt="<?= $page->title ?>"> addHookMethod goes into /site/init.php <?php /* Returns URL of the original Pageimage of Article. * Image field's value can be either null (default missing image), Pageimage or Pageimages. * * @return string */ $wire->addHookMethod('Page::siteFeaturedImage', function($event) { $page = $event->object; if ($page->template != "article") { throw new WireException("Page::siteFeaturedImage() only works on 'Pages of article template', Page ID=$page is not such!"); } $article_featured = $page->getUnformatted('article_featured'); //always a Pageimages array if (count($article_featured)) { $img_url = $article_featured->first()->url; } else { $img_url = urls()->templates . "assets/img/missing-article_image.jpg"; //we show this when image is not available } $event->return = $img_url; }); ?> #2 Example template file code: <?php $img600_src = $page->siteProductImageMaxSize(600, 600, ['rotate' => 180]); ?> <img src="<?= $img600_src ?>" alt="<?= $page->title ?>"> addHookMethod goes into /site/init.php <?php /* Generates image variations for Product images. Returns URL of Pageimage. * Image field's value can be either null (default missing image), Pageimage or Pageimages. * * @param int arguments[0] Max allowed width * @param int arguments[1] Max allowed height * @param array arguments[2] See `Pageimage::size()` method for options * @return string */ $wire->addHookMethod('Page::siteProductImageMaxSize', function($event) { $page = $event->object; if ($page->template != "product") { throw new WireException("Page::siteProductImageMaxSize() only works on 'Pages of product template', Page ID=$page is not such!"); } $width = isset($event->arguments[0]) ? $event->arguments[0] : 48; //default width $height = isset($event->arguments[1]) ? $event->arguments[1] : 48; //default height $options = isset($event->arguments[2]) ? $event->arguments[2] : $options = array(); //default empty options $product_image = $page->getUnformatted('product_image'); //always a Pageimages array if (count($product_image)) { $img_url = $product_image->first()->maxSize($width, $height, $options)->url; } else { $img_url = urls()->templates . "assets/img/product-missing-image.jpg"; //we show this when image is not available } $event->return = $img_url; }); ?> BTW, you can find more examples here: How can I add a new method via a hook? Working with custom utility hooks Adding array_chunk support to WireArray addHookProperty() versus addHookMethod() Have a nice weekend!
    3 points
  4. If you want to see the current situation real-time, you could install the built-in Session Handler DB module. This changes ProcessWire to use database sessions (instead of storing session data on the disk) and also provides a handy overview under Setup > Sessions that displays currently active users, when they last did something, and where they are on the site right now. I'm not aware of a module that would track this kind of data in the long term and/or store it in a log file, but I'm guessing that it wouldn't be terribly difficult to build one on top of the database sessions module. Someone else might have a better idea about this though. The Login History module tracks when users last logged in, but it doesn't track logouts, so it's probably not much of a help in this case.
    3 points
  5. @teppo Thanks for the tip. Was a bit confused about naming conventions. The module doesn't render anything so not Markup, and to me, it was a 'process', although granted, not a PW process. Done. Let me know if there are any problems relating to the name change.
    3 points
  6. Thanks for sharing this module, @psy! Will definitely give this a try soon. Just one observation at this point: only Process modules should have the Process prefix in their name, and since this isn't a Process module (i.e. it doesn't extend Process), I'd suggest considering another name for clarity. Perhaps just dropping the Process prefix?
    3 points
  7. The reason for that is that the global keyword always refers to the global scope, i.e. the highest scope possible. In this case $gsAPIKey is first defined in a function scope, not in the global scope.. so no help from the global keyword You should either define $sgAPIKey within send_email(), as shown in the example above, or you could define it earlier and pass it as an additional param to the function.
    3 points
  8. Just some explanation because it is interesting... This isn't something that is specific to Repeaters - it applies to any selector used on a PageArray/WireArray (a Repeater field returns a PageArray). When you do $some_pagearray->find() this is different to a $pages->find() - the method name is the same but they are actually totally different methods. See find() method in the PageFinder class vs the WireArray class. When using $pages->find() the method refers back to the fieldtype for each queried field and the fieldtypes can do some special preparation to the queried value. In the case of a Datetime field the value is passed through strtotime() if it is a string. So this allows "today" to be converted to a timestamp. But when using $some_pagearray->find() this process does not happen, so the queried value must be a timestamp. Another gotcha to watch out for is using the page status as a string in a selector. With $pages->find() you can do something like "status!=hidden" but this won't work with a selector in $some_pagearray->find(). I think it would be nice if things like this did work with PageArrays - there is an open request for it.
    3 points
  9. Sure! See the snippet below if ($input->post->submit) { // === When submit button is clicked if ($v->validate()) { // === Validate the data if ($captcha->verifyResponse() === true) { // === Verify Captcha $subject = 'Contact Form'; // === Subject $messageHTML = include_once('partials/contact/_email.php'); // === Get the message, is in HTML $mail = wireMail() // === Set up the mail data ->to($contactFormRecipient) ->header('Reply-To', $email) ->subject($subject) ->bodyHTML($messageHTML); if ($mail->send()) { // === If mail is sent, while sending e-mail $session->flashMessage = __('Thank you for your message! We will get back to you.'); $session->sent = true; $session->redirect($page->url); } else { // === If mail isn't sent $session->flashMessage = __('Mail not sent. Error occured.'); } } else { // === Captcha error $session->flashMessage = __('Recaptcha Validation Error'); } } else { // === Validation errors $session->flashMessage = __('Please correct the errors and try again.'); } }
    2 points
  10. There's also $pages->count(selector) method available. <?php $today = strtotime('today'); // $today = strtotime('now'); is also available // count pages that have expired before today $alertCount = $pages->count("parent.template=client, expiration_date<=$today"); https://processwire.com/api/ref/pages/count/ FYI, you dont have to convert date back and forth, strtotime returns UNIX timestamp, and PW understands it perfectly.
    2 points
  11. Checking expiration_date in the selector should do the trick. $todaysdate = date("F j, Y H:i"); $today = strtotime($todaysdate); $ads = $pages->find("parent.template=client, expiration_date<$today, sort=expiration_date"); echo count($ads);
    2 points
  12. Hi, I think if you replace this: $m->to($contactFormRecipient) ->from($email) ->subject('Contact form submission') ->bodyHTML($message) ->send(); with the following: $m->to($contactFormRecipient) ->from($email) ->subject('Contact form submission') ->bodyHTML($message); that it will work and the email will be send one time, that's how my contact form works , I hope this helps you ~ Harmen
    2 points
  13. Tip: By default the Dropbox App is in Development mode and allows only one user - you. When you apply for a token you may get a Dropbox notification saying you need more users. Simply go back into your Dropbox App configuration and click on the button to the right of this setting. You'll automatically be granted 500 development users. Should you need more than 500 users, you'll need to apply to Dropbox for Production status for your App and totally outside the scope of this ProcessWire Dropbox API module.
    2 points
  14. Or better yet, under API & Templates? Some sections have subsections like Modules/Plugins -> Module/Plugin Development It would be great to see: API & Templates - Bootstrap - Zurb Foundation - UIkit - Others
    2 points
  15. Hi @holmescreek Have you already considered taking a closer look at @bernhard's RockDataTables? DataTables supports Complex headers (rowspan and colspan). Should you decide to implement your own module, there is another free package called W2UI which also supports it.
    2 points
  16. Changed it to DropboxAPI
    2 points
  17. Thank you! This is very useful because I'm not a php expert. Welcome everyone!
    2 points
  18. OAuth2Login for ProcessWire A Module which give you ability to login an existing user using your favorite thrid-party OAuth2 provider (i.e. Facebook, GitHub, Google, LinkedIn, etc.).. You can login from the backend to the backend directly or render a form on the frontend and redirect the user to a choosen page. Built on top of ThePhpLeague OAuth2-Client lib. Registration is not handled by this module but planned. Howto Install Install the module following this procedure: - http://modules.processwire.com/modules/oauth2-login/ - https://github.com/flydev-fr/OAuth2Login Next step, in order to use a provider, you need to use Composer to install each provider ie: to install Google, open a terminal, go to your root directory of pw and type the following command-line: composer require league/oauth2-google Tested providers/packages : Google : league/oauth2-google Facebook: league/oauth2-facebook Github: league/oauth2-github LinkedIn: league/oauth2-linkedin More third-party providers are available there. You should be able to add a provider by simply adding it to the JSON config file. Howto Use It First (and for testing purpose), you should create a new user in ProcessWire that reflect your real OAuth2 account information. The important informations are, Last Name, First Name and Email. The module will compare existing users by firstname, lastname and email; If the user match the informations, then he is logged in. ie, if my Google fullname is John Wick, then in ProcessWire, I create a new user Wick-John with email johnwick@mydomain.com Next step, go to your favorite provider and create an app in order to get the ClientId and ClientSecret keys. Ask on the forum if you have difficulties getting there. Once you got the keys for a provider, just paste it into the module settings and save it. One or more button should appear bellow the standard login form. The final step is to make your JSON configuration file. In this sample, the JSON config include all tested providers, you can of course edit it to suit your needs : { "providers": { "google": { "className": "Google", "packageName": "league/oauth2-google", "helpUrl": "https://console.developers.google.com/apis/credentials" }, "facebook": { "className": "Facebook", "packageName": "league/oauth2-facebook", "helpUrl": "https://developers.facebook.com/apps/", "options": { "graphApiVersion": "v2.10", "scope": "email" } }, "github": { "className": "Github", "packageName": "league/oauth2-github", "helpUrl": "https://github.com/settings/developers", "options": { "scope": "user:email" } }, "linkedin": { "className": "LinkedIn", "packageName": "league/oauth2-linkedin", "helpUrl": "https://www.linkedin.com/secure/developer" } } } Backend Usage In ready.php, call the module : if($page->template == 'admin') { $oauth2mod = $modules->get('Oauth2Login'); if($oauth2mod) $oauth2mod->hookBackend(); } Frontend Usage Small note: At this moment the render method is pretty simple. It output a InputfieldForm with InputfieldSubmit(s) into wrapped in a ul:li tag. Feedbacks and ideas welcome! For the following example, I created a page login and a template login which contain the following code : <?php namespace ProcessWire; if(!$user->isLoggedin()) { $options = array( 'buttonClass' => 'my_button_class', 'buttonValue' => 'Login with {provider}', // {{provider}} keyword 'prependMarkup' => '<div class="wrapper">', 'appendMarkup' => '</div>' ); $redirectUri = str_lreplace('//', '/', $config->urls->httpRoot . $page->url); $content = $modules->get('Oauth2Login')->config( array( 'redirect_uri' => $redirectUri, 'success_uri' => $page->url ) )->render($options); } The custom function lstr_replace() : /* * replace the last occurence of $search by $replace in $subject */ function str_lreplace($search, $replace, $subject) { return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1); } Screenshot
    1 point
  19. I've been using clamp http://jide.github.io/clamp/ for a while now, rather than installing MAMP or MAMP PRO. Like MAMP, it delivers Apache, MySQL (via MariaDB), and PHP. Unlike MAMP it runs from the command line (the 'c' in clamp). Also unlike MAMP, all settings and data (database), sit alongside the website files in a .clamp folder (you need to add this to .gitignore to stop dev environment leaking into production). Apart from being free, it's just brilliant to use. If you get errors or stuck, check the logs, the docs are brief but excellent. Enjoy!
    1 point
  20. Hi Zeka, Take a look of this amazing module which does the job for you. http://modules.processwire.com/modules/admin-restrict-branch/ Gideon
    1 point
  21. You can use AND operator for that. https://processwire.com/api/selectors/#and-selectors <?php $today = new \DateTime(); // set to now $inFiveDays = $today->modify('+5 days'); $tsToday = $today->getTimestamp(); $tsInFiveDays = $inFiveDays->getTimestamp(); // selectors are built in the order: field<operator>value // repeat a field for AND operation $ads = $pages->find("parent.template=manufacturer, expiration_date>=$tsToday, expiration_date<=$tsInFiveDays, sort=expiration_date");
    1 point
  22. Glad it works now! Good luck with the further development of your website!
    1 point
  23. My original code: $m->to($contactFormRecipient) ->from($email) ->subject('Contact form submission') ->bodyHTML($message) ->send(); // SEND #1 if ($m->send()) { // SEND #2 I totally didn't notice the parenthesis in the if block. Doh! It sends the mail, then returns true/false presumably. You were right in your first reply. Thanks @Harmen All working now Full code here (bootstrap 4 alpha 6): <?php namespace ProcessWire; wireIncludeFile("./vendor/vlucas/valitron/src/Valitron/Validator.php"); $captcha = $modules->get("MarkupGoogleRecaptcha"); $contactPageID = '1020'; $contactFormRecipient = 'MY_EMAIL_ADDRESS'; $name = $sanitizer->text($input->post->name); $email = $sanitizer->email($input->post->email); $message = $sanitizer->text($input->post->message); $v = new \Valitron\Validator(array( 'name' => $name, 'email' => $email, 'message' => $message ) ); $v->rule('required', ['name', 'email', 'message']); $v->rule('email', 'email'); if ($input->post->sendMe) { if ($v->validate()) { if ($captcha->verifyResponse() === true) { $message = " <html> <body> <p><b>From:</b></p> <p>{$name}</p> <p><b>Email:</b></p> <p>{$email}</p> <p><b>Message:</b></p> <p>{$message}</p> </body> </html> "; $mail = wireMail(); $mail->to($contactFormRecipient) ->header('Reply-To', $email) ->subject('JS Electrician form submission') ->bodyHTML($message); if ($mail->send()) { $session->flashMessage = "<h2>Thank you for your message! I will get back to you shortly.</h2>"; $session->sent = true; $session->redirect($pages->get($contactPageID)->url); } else { $session->flashMessage = "<h2>Sorry, an error occured. Please try again.</h2>"; } } else { $session->flashMessage = '<h2>Recaptcha must be complete.</h2>'; } } else { $session->flashMessage = 'Please fill out the fields correctly.'; } } ?> <div class="container"> <div class="row justify-content-between"> <div class="col-sm-12 col-lg-8 py-3"> <?php if($session->flashMessage):?> <div class="alert <?php echo $session->sent ? 'alert-success' : 'alert-danger'?>" role="alert"> <?php echo $session->flashMessage;?> </div> <?php endif;?> <form id="contact-form" method="post"> <div class="row"> <div class="form-group col-sm-12 col-lg-6 py-2 <?php echo $v->errors('name') ? 'has-danger' : ''?>"> <label for="name">Name (required)</label> <input class="form-control" name="name" id="name" type="text" value="<?php echo $sanitizer->text($input->post->name); ?>"> </div> <div class="form-group col-sm-12 col-lg-6 py-2 <?php echo $v->errors('email') ? 'has-danger' : ''?>"> <label for="email">Email (required)</label> <input class="form-control" name="email" id="email" type="text" value="<?php echo $sanitizer->text($input->post->email); ?>"> </div> </div> <div class="form-group py-2 <?php echo $v->errors('message') ? 'has-danger' : ''?>"> <label for="message">Message (required)</label> <textarea class="form-control" name="message" id="message" rows="8"><?php echo $sanitizer->text($input->post->message); ?></textarea> </div> <div> <!-- Google Recaptcha code START --> <?php echo $captcha->render(); ?> <!-- Google Recaptcha code END --> </div> <div class="form-group"> <button type="submit" class="btn btn-primary" name="sendMe" value="1">Send message</button> </div> </form> </div> <div class="col-sm-12 col-lg-3 py-3"> <h2>Have a question?</h2> <p class="mb-0"><i class="fa fa-phone" aria-hidden="true"></i> <?php if($clientPhone) echo $clientPhone; ?></p> </div> </div> </div> <?php $session->remove('flashMessage'); $session->sent = false; echo $captcha->getScript(); ?>
    1 point
  24. One thing to make your foreach loop a bit smaller and faster is to move these lines of code (below). Just set them before the foreach loop. As far as I can see you are checking the date for each ad, but it's always the same so it's faster to define it once. $todaysdate = date("F j, Y H:i"); $today = strtotime($todaysdate); So that results in this: $ads = $pages->find("parent.template=client, sort=expiration_date"); // === Get $ads $alert_count = 0; // === Set alert count $todaysdate = date("F j, Y H:i"); // === Get the date $today = strtotime($todaysdate); // === Make a string from the date foreach ($ads as $ad) { // === Start foreach $expireson = $ad->expiration_date; $expires = strtotime($expireson); // === I think you can also shorten this to $expires = strtotime($ad->expiration_date); Maybe you can even try $fiveaway = strtotime($ad->expiration_date) - 432000; $fiveaway = $expires - 432000; if ($today > $expires) { $alert_count += 1; } } // === End Foreach echo $alert_count; // === Echo the counter result Hope this helps...
    1 point
  25. You are not incrementing $alert_count. It should be : $alert_count += 1; // not =+ 1;
    1 point
  26. AdminOnSteroids has nothing to do with the frontend.
    1 point
  27. Hi, We can better help you if you provide more info such as your code and your textarea field settings. Gideon
    1 point
  28. btw: the (no so cheap) pro version of handsontable allows nested headers: https://docs.handsontable.com/pro/1.4.0/demo-nested-headers.html but i don't know if that would work with my module...
    1 point
  29. I read "I need to output data for a table" so input did not occurred to me, but I might be totally wrong. Sorry for that. Besides, I forgot the name of this other table module of yours (Handsontable). Thanks for reminding us
    1 point
  30. hi, could be a perfect fit for my Handsontable module: if the headers are always the same you could just set them up in your field settings. the problems with my module are that the field will not be queryable (does that word exist?) and that it is currently not easily possible to add columns to the field lateron since the field settings will change but the data stored in the field will not. if that's no problem for you it could be worth a try @szabesz the datatables module is more for presentation inside the admin, not for input
    1 point
  31. I know the point of PW forums is to discuss PW. I was just wondering if any consideration can maybe given to set up maybe a forum section called 'Front End Frameworks & PW', and maybe just a couple subsections like 'Bootstrap' and 'Zurb Foundation', (just maybe 3 of the most popular frameworks), to discuss questions integrating those with PW?
    1 point
  32. Absolutely - Google is quite often wrongly thought to be the enemy. Not at all, unless people are trying to cheat in some way. They actually do their best to understand broken site architecture, which is something that PW does a great job of helping us avoid anyway. And we can easily go for a belt & braces approach by adding <link rel="canonical" href="<?=$page->url?>"> in our site's <head>...</head>, letting PW handle it. (Might very well be unnecessary, but can't hurt.)
    1 point
  33. I might be misunderstanding what you meant by "discounting of the value" and "counted", but the sources I've read so far seem to say that, behind the scenes, duplicate content is automatically bundled together under one canonical URL by Google. In this case it could mean that, for an example, all links to example.com/foo and example.com/foo/ would count towards the version that Google deems "primary", and it would also be the only one they display in their search results (unless the user specifically chooses to show duplicate content). Possibly the most common problem with duplicate content is that Google could choose a different version as the primary one than what you might prefer, unless you use canonical tags to advice them. Probably the most fearsome problem, on the other hand, would be that they could think that you're trying to copy same content over and over as an attempt to "cheat", in which case they could remove some pages, or even the whole site, from their search index. But again, I highly doubt that they could ever interpret a trailing slash issue as such an attempt I must admit that crawl budget was a new concept for me. After reading a bit about it, I'd say that it definitely won't be an issue for the vast majority of us here (first of all in a blog post they say that it usually only affects sites with thousands of pages), but it's definitely something that very large sites, or sites that auto-generate URLs in some way, should take into consideration. Anyway, thanks for sharing this point of view!
    1 point
  34. That's the whole thing in a nutshell. Don't sweat the tiny details FWIW I don't think of the 'duplicate content penalty' as a penalty per se, more a discounting of the value of any content that is identified as a duplicate of some other content that is counted. If there is a negative, it's that it costs your crawl budget. By which I mean that say Google is prepared to crawl 10 pages of your site per visit, if 2 of those pages are the same content under very slightly different URLs, you are blowing the opportunity to have another actual different page crawled. Having said that, and getting back to the point, there are any number of more significant things to be spending time on.
    1 point
  35. Hi @Lance O. You can do it by specifying needed selector in the field options or with hook.
    1 point
  36. Is anyone seeing a problem with the new image tags, where all of the image or file tags disappear when you upload a new item? Its happening to me on 3.0.70 on file and image fields. Thankfully the tags do not get removed from the items, but they all become invisible when you add an image or file. I'm guessing the core InputfieldFile is reloading the field after upload but the selectized fields are maybe not set to reinit on reloaded ? Here is a GIF of the behavior when using core selectize image tags: Here is it working correctly, using the module init of the field (same core selectize version)
    1 point
  37. looks like adding new pages to the field should just be a matter of adding 2 selectors in the page field edit links module, so that it can be inclusive/aware of Selectize inputfield.
    1 point
  38. I understand now what you mean by no error. There is one last error, which can be seen if you dump the variable $response. You could see that SendGrid return an error code which can be something like that : statusCode => 401 body => "{"errors":[{"message":"Permission denied, wrong credentials","field":null,"help":null}]}" The reason is that the global $sgAPIKey in the function is not getting the value from the $sgAPIKey defined with the key (from some reason that someone might explain here..) To solve the issue, just set your API key in the function directly. [...] function send_email($from_email, $to_email, $subject, $body) { $sgAPIKey = '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'; // Lucy [...]
    1 point
  39. Hi @flydev Nice to see you again. Looks like you are back on track. Any plans on working on this great module again? You have probably been waiting for this question
    1 point
  40. @oma Call SendGrid like that : new \SendGrid(); (As Adrian said, its a namespace issue) @teppo I used WireFileTools just for the example, the bénéfit of this class is that it provide the ProcessWire API to the object. Sorry for the short answer, i am on mobile.
    1 point
  41. I also agree, but I'm not sure such a tool would be helpful since Ryan has his own way of doing things. What we need is more or less visible by looking at open issues, pull requests and feature requests.
    1 point
  42. Aha, yes! Thank you! I keep forgetting that we have unformatted values too. I updated both methods in my original post. Cheers,
    1 point
  43. @arjen Thanks for your suggestion. Hopefully my publish does not cause much issue here. Sorry if I have violated something. I wondered if it is appropriate to fork a project with 90% code changed or instead fork to SessionHandlerDB with more similarity. I will try to fork SessionHandlerRedis later. Hope that netcarver is still interested in this module.
    1 point
×
×
  • Create New...