Jump to content

Leaderboard

Popular Content

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

  1. Finally got a chance to try it and this module is great, and will solve innumerable content management conundrums.. Here's my first use, on a quotes rotator section: Field Config: var colheaders = ['Author', 'Publication', 'Quote']; hot.updateSettings({ colHeaders: colheaders, minCols: colheaders.length, maxCols: colheaders.length, rowHeaders: false, minRows: 1, minSpareRows: 1, maxRows: 5, width: 900, contextMenu: true, autoWrapRow: true, autoWrapCol: true, colWidths: [200,200,500], }); edit screen: output:
    3 points
  2. In this week's post we'll take a closer look at the importing side of our upcoming export/import tool. Plus we'll look at something new in 3.0.70 called markup region hints, which are worthwhile if you are using markup regions in PW3. https://processwire.com/blog/posts/pw-3.0.70/
    3 points
  3. A couple more links that may be useful:
    2 points
  4. Who is creating the pages? You (the developer), or a client? If you are creating the pages then I think it would be better to use the API or a bulk import module (ImportPagesCSV, BatchChildEditor) to bring this data in initially rather than spend time making something special in Page Edit. API $countries_string = 'Nigeria, Kenya, Australia, Russia, France'; // Maybe you would instead create an array of country strings to process multiple pages at once // 'Page One Title' => 'Nigeria, Kenya, Australia, Russia, France', // 'Page Two Title' => 'Russia, ...' // ... $country_titles = explode(', ', $countries_string); $country_pages = $pages->find([ 'template' => 'country', 'title' => $country_titles, ]); // Set $country_pages to the Page Reference field ImportPagesCSV Use a text editor to replace instances of ', ' with '|' in your countries string. Now the country titles are in a format that can be imported to a Page Reference field by ImportPagesCSV (see the module readme). You could import all the page content via the module, or just the countries field if you prefer (create a CSV that contains two columns - the page title and the pipe-separated string of country titles).
    2 points
  5. The JquerySelectize module, that all of the other Selectize family modules require, has been updated (to version 1.0.1) as follows: 1) Checks to see if the core version is 3.0.67 or higher (version at which selectize was added to core), and if so, will load the core files, and not this module's files. Using the ProcessWire core versions of selectize.js improves the user experience, because of the adjustments that Ryan made to the plugin, which relates to hitting enter key after typing a tag (which would by default submit the form). 2) In addition to loading the CSS & JS from the core, when working in versions 3.0.67 or higher, the module still provides a skin selector. While most users will probably stick to the core non-skinned version of Selectize, the module provides this option to choose a different skin. There are some scenarios where choosing the default or bootstrap skins for selectize can be preferable, as they may be higher contrast or more pronounced with color usage, and can help in some ways with accessibility for users with any type of vision impairment. Currently the update/behavior only applies to Selectize modules family that require and use the JquerySelectize module, so if you are using core image tags and have this module installed, it won't change the skin; However there is a plan to try and hook into the image field rendering and enable this module to add the custom selected skin to the css files.
    2 points
  6. Hi everyone, I'm proud to share my first fieldtype module and I think it's a quite handy one It helps you to create all kinds of table/matrix inputs very quickly and easily. You have loads of options for customizing your field via plain javascript. See the handsontable docs for that Please consider this module ALPHA until i got some more time to test it. Any help would be highly appreciated Numbers are for example always tricky. Different locale settings, different types, rounding errors and so on... Download: https://gitlab.com/baumrock/FieldtypeHandsontable Result: Installation/Configuration: Just install the Fieldtype, add a field to your template and set the handsontable options in the fields details. If you have InputfieldAceExtended installed you will also have code highlighting for your code: Get data: If you retrieve the data from the API with outputformatting ON you have some helper methods available: getData() + getRows() get all data of the field getRow($row) get one special row, eg getRow(1) or getRow("2017") getCols() get all data but by columns not by rows getCol($col) get one special column, eg getCol(1) or getCol("mycolumnheader") You can also access rowHeaders and colHeaders directly (see examples) Simple Example: Caution: the examples below are outdated! see this post:
    1 point
  7. 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
  8. You can show the field when the countries field is empty using the core inputfield dependencies feature: countries.count=0 Or you could show it when the page is unpublished (which would apply when the page is first added) with the help of my Custom Inputfield Dependencies module.
    1 point
  9. To me the main distinction is between the bulk importing of data (for which modules like ImportPagesCSV are great) and the occasional addition or editing of data which you do via Page Edit. But in any case it's not difficult to do what you are asking about. Add a textarea field in your template named "country_import" or something. Then use a hook to Pages::saveReady() to process the field contents and add them to the "countries" Page Reference field. In /site/ready.php: $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); // Only for the appropriate template if($page->template == 'YOUR-TEMPLATE') { // If the import field is not empty if($page->country_import) { // Get the individual country titles in an array $country_titles = explode(', ', $page->textarea_1); // Find the country pages with those titles $country_pages = $this->pages->find([ 'template' => 'country', 'title' => $country_titles, ]); // Add the country pages to the countries field $page->countries->add($country_pages); // Empty the import field $page->country_import = ''; } } }); You could use the same principle for other fields if you think there's a major benefit to it.
    1 point
  10. Hi @adrianmak You can achieve this by using hooks and my ReCaptcha module. First install the MarkupGoogleReCaptcha module then in file ready.php, write the following code : /* * 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); } /* * replace the FIRST occurence of $search by $replace in $subject */ function str_freplace($search, $replace, $subject) { $from = '/'.preg_quote($search, '/').'/'; return preg_replace($from, $replace, $subject, 1); } $captchamod = wire('modules')->get("MarkupGoogleRecaptcha"); wire()->addHookProperty('Page::captcha', function($event) use ($captchamod) { $event->return = $captchamod; }); wire()->addHookAfter('Page::render', function($event) { $template = $event->object->template; $page = $event->object; if ($template == 'admin' && !wire('user')->isLoggedin()) { $captchaScript = $page->captcha->getScript() . '</body>'; $captchaHtml = $page->captcha->render() . '</form>'; $event->return = str_freplace('</form>', $captchaHtml, $event->return); $event->return = str_lreplace('</body>', $captchaScript, $event->return); } }); wire()->addHookAfter('Session::authenticate', function($event) { $page = wire('page'); $template = $page->template; if ($template == 'admin') { if ($page->captcha->verifyResponse() == false) { wire('session')->logout(); wire('session')->redirect(wire('config')->urls->admin); } } });
    1 point
  11. A few references to Hooks: https://processwire.com/api/hooks/ https://somatonic.github.io/Captain-Hook/index.html https://github.com/adrianbj/TracyDebugger/tree/master/panels/CaptainHook http://www.flamingruby.com/blog/using-hooks-to-alter-default-behavior-of-processwire/ https://webdesign.tutsplus.com/tutorials/a-beginners-introduction-to-writing-modules-in-processwire--cms-26862
    1 point
  12. To solve this you need to look at the code for each method you are considering hooking and ask yourself things like: What class is the method in? Does the method fire when I need it to? Does the method have an argument or return value that I need to use in my hook? So you are considering hooking ProcessLogin::afterLogin() or Session::loginSuccess(). When you look at afterLogin() you see: It is a method of ProcessLogin, a Process module that handles the PW login form. So it is only going to fire if a user logs in via the core PW login form. Maybe that isn't what you want if you are using a custom login form or logging in users via the API as part of some script. It depends on what you are doing. The method comments in the source code say it is only intended for when a superuser logs in, which could give you a clue if it is the best method to hook or not. It has no arguments that could be useful to quickly tell you things about the user who has logged in (although you could still get the $user object in other ways). So chances are Session::loginSuccess() is going to be a better option because it is a method of Session, so more closely connected to the current user session regardless of how they logged in. And it conveniently has the $user object as an argument so you can easily check properties of the user such as name, role, etc, in your hook.
    1 point
  13. Hi, just stumbled over a little module that i built for my last project. it helped me to test performance of my rockdatatables module to generate 3000 random json datasets and i want to share it with you. maybe it saves some time for someone. https://gitlab.com/baumrock/RockDummyData/ easy example: $rdd = $modules->get('RockDummyData'); for($i=0; $i<15; $i++) { // this has to be inside the for-loop to always get a new dummy $dummy = $rdd->getDummy(); echo date("d.m.Y H:i:s", $dummy->timestamp) . "<br>"; } more advanced: $json = new stdClass(); $json->data = array(); $rdd = $modules->get('RockDummyData'); for($i=0; $i<3000; $i++) { // this has to be inside the for-loop to always get a new dummy $dummy = $rdd->getDummy(); $obj = new stdClass(); $obj->name = $dummy->forename . ' ' . $dummy->surname; $obj->position = $dummy->job; $obj->office = $dummy->city; $obj->color = $dummy->color; $obj->start_date = new stdClass(); $obj->start_date->display = date('d.m.Y',$dummy->timestamp); $obj->start_date->sort = $dummy->timestamp; $obj->salary = rand(0,10000); $json->data[] = $obj; } echo json_encode($json); you have to store your random datasets on your own into the /data folder. there are several services for creating all kinds of random data on the web - if you know one service that allows sharing those datasets let me know and i can include common needed data into the module
    1 point
  14. Adding the setlocale statement is not a hard requirement, but you'd need to live with the pw notice each time you log in. It's been added not because of anything related to multi-language sites, but because of issues with file handling of processwire involving utf-8 characters like cyrillic ones. These can happen on all processwire sites not just multi language ones.
    1 point
  15. There's no reference, it's a normal page. The only reference is the pagetable field itself. Ring a bell? $thepage = $pages->get("template=basic-page, mypagetable=$page");
    1 point
  16. I implemented a similar thing a while ago and ended up with the code below. I think it was pieced together base on some previous code we had lying around at the company, and I'm not sure why the distance value is so precise at 8.047. It's not a perfect circular distance either, but it seems to work for what was needed at the time. // $lat and $lng should be float values of the location to search $distance = 8.047; //in km $radius = 6371; // earth's radius in km = ~6371 // latitude boundaries $maxlat = $lat + rad2deg($distance / $radius); $minlat = $lat - rad2deg($distance / $radius); // longitude boundaries (longitude gets smaller when latitude increases) $maxlng = $lng + rad2deg($distance / $radius / cos(deg2rad($lat))); $minlng = $lng - rad2deg($distance / $radius / cos(deg2rad($lat))); $query = "coords.lat>=$minlat, coords.lat<=$maxlat, coords.lng>=$minlng, coords.lng<=$maxlng"; In that code, 'coords' is the mapmarker field.
    1 point
  17. There are several options: Check if the $p has a specific template (or any other field). if(count($children) > 0 && $p->is("template!=news-item|other|template")) Or exclude above the loop like: $children = $p->children->not("template=news-item|other|template"); Or filter above the loop like: $children = $p->children->filter("template!=news-item|other|template"); See the excellent cheatsheet for more options in the PageArray/WireArray. Another option might be to use to use soma's navigation module.
    1 point
×
×
  • Create New...