Leaderboard
Popular Content
Showing content with the highest reputation on 05/26/2024 in Posts
-
Ryan said in the previous announcement that you can use a hook to set which pages become editable. So you could use this to make the grandchildren editable, or the children and the grandchildren if you wanted the child pages to serve as a kind of visual divider between the categories of options. Edit: example... // Define custom "children" for PageEditChildren $wire->addHookAfter('PageEditChildren::getChildren', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); if($page->template == 'blank') { $items = new PageArray(); foreach($page->children as $child) { $items->add($child); foreach($child->children as $grandchild) { $items->add($grandchild); } } $event->return = $items; } }); // Hook rendering of PageEditChildren "child" fieldsets // to apply a data attribute for identifying the template // It would be cool if PageEditChildren did this by default $wire->addHookBefore('InputfieldFieldset::render', function(HookEvent $event) { /* @var $fieldset InputfieldFieldset */ $fieldset = $event->object; $wrap_class = $fieldset->wrapClass(); if($wrap_class !== 'PageEditChild') return; $attr = $fieldset->wrapAttr(); if(!isset($attr['data-page'])) return; $p = $event->wire()->pages->get($attr['data-page']); if(!$p->id) return; $fieldset->wrapAttr('data-template', $p->template->name); }); Custom admin SCSS: li.PageEditChild[data-template="references"] { > .InputfieldHeader { background-color:#f0f3f7 !important; } }6 points
-
@Robin S Thanks for that detailed example. I actually did experiment with that hook before my post as well, and as your example demonstrates, you kind of have to hack it to show grandchildren in-line with their parents. Sorting then becomes weird because they are technically at different depths. This isn't the best UX. Ideally, if you expanded/opened the "Colors" child page, then it would show it's children "contained" inside of it, in a way that's somewhat similar to nested repeaters without repeaters. I was wondering if native support for the approach I described would be too much of a stretch given how PageEditChildren is currently programmed.1 point
-
@kongondo great work as always! Loving how easy it is to use the new customers and customer groups to create a custom dashboard for them. I've made an address book so that customers can create/update/delete addresses with ease and view/manage their orders. Next up will be to integrate the address book into the customer information form at checkout, rather than set the default address. This will be fun to work on ? Likewise, it was straightforward to get the discount codes feature integrated and this is working very well indeed. Really can't applaud your work on this big update enough!!! ????1 point
-
Hi, I have updated the 009 release. In summary: Add method to PadloperDiscounts Class to remove all discounts applied to an (in session) order - removeDiscounts(). Thanks @alexm for the suggestion. Fix for missing 'padloper-customer' role that is given to Padloper customers for easier identification, etc. Thanks @alexmfor catching this. Fix for missing 'other optional settings' in the installer modal in list of actions to be applied when configuring Padloper. Thanks @alexm for catching this. Thanks.1 point
-
I've written a utility for working with .env files in ProcessWire and it makes use of the directory structure in the great post shared by @netcarver. I think this addresses the items brought up here about vendor directory placement and also provides a clean and simple method of implementation while providing some handy tools to boot. You can view and download the code for this .env implementation strategy from this repository. This reads and caches .env file variables and makes them easy to work with in the ProcessWire config.php file. The readme in that repository provides a full rundown of directory structure and setup. Here's an overview of how it's used once you've configured it in your project. <?php namespace ProcessWire; /** * Example usage in config.php **/ use App\Env\Env; if(!defined("PROCESSWIRE")) die(); $env = Env::load(); // You can now access any variable in the .env file located in your root directory with an accessor method $env->get('YOUR_ENV_VARIABLE'); // => returns whatever that value is in .env // You can optionally make env values accessible globally in ProcessWire by assigning $env to a property // Then you can use $config->env->get('NAME_OF_VARIABLE'); $config->env = $env; // Use to set up your config values $config->debug = $env->get('DEBUG'); // ... But hey, why stop there? You can also do this: <?php namespace ProcessWire; /** * Example config.php file */ use App\Env\Env; if(!defined("PROCESSWIRE")) die(); $env = Env::load(); $config = $env->pushToConfig($config, [ 'useFunctionsAPI' => 'USE_FUNCTIONS_API', 'usePageClasses' => 'USE_PAGE_CLASSES', 'useMarkupRegions' => 'USE_MARKUP_REGIONS', 'prependTemplateFile' => 'PREPEND_TEMPLATE_FILE', 'appendTemplateFile' => 'APPEND_TEMPLATE_FILE', 'templateCompile' => 'TEMPLATE_COMPILE', 'dbHost' => 'DB_HOST', 'dbName' => 'DB_NAME', 'dbUser' => 'DB_USER', 'dbPass' => 'DB_PASS', 'dbPort' => 'DB_PORT', 'dbEngine' => 'DB_ENGINE', 'userAuthSalt' => 'USER_AUTH_SALT', 'tableSalt' => 'TABLE_SALT', 'chmodDir' => 'CHMOD_DIR', 'chmodFile' => 'CHMOD_FILE', 'timezone' => 'TIMEZONE', 'defaultAdminTheme' => 'DEFAULT_ADMIN_THEME', 'installed' => 'INSTALLED', 'debug' => 'DEBUG', ]); // Arrays aren't for .env files... $config->httpHosts = ['yourdomain.com']; // You can also get all of the values at once with this method $env->toArray(); What this does behind the scenes: Parses the .env file Casts booleans and ints appropriately where detected Caches the .env values in a file located outside of the public directory (read why below) Provides utility methods to access the .env data Optionally loads values to the server $_ENV array Values provided by the Env object are immutable Because ProcessWire has pretty much all of it's out-of-the-box configurations located in config.php, by default this only loads the values and makes them accessible via the get() method available on the object returned by Env::load(), not via $_ENV. You can optionally make your values available in $_ENV by passing 'true' to the load() method. About caching... This uses phpdotenv to read the .env file and load it's contents. There is some overhead for this process and requires significantly more work than just turning the .env into a key/value array. This application uses phpdotenv to parse the file then stores that in a cache file called env.php as a native array which is then subsequently loaded using require_once, an operation that is trivial for PHP to handle. Additionally, the object returned by Env::load() memoizes all values so the cached file is only read once during application execution and all subsequent key/value access is pulled from memory. Cache can be cleared using a provided method. I like how this came out and hope others find it useful. Interested in everyone's thoughts. It would really be great if installation and directory configuration were automated in a bash script, but I don't have the time. Pull requests are wide open for that ?1 point
-
Awesome@Juergen, really nice work ? I've added a working demonstration of a customized security question using the new compareTexts validator to the PicoWire site profile If you want to add a customized CAPTCHA question to your form, disable CAPTCHA in the module configuration, and then add a custom text input with the new validator set as a rule // add security question field $question = new \FrontendForms\InputText("question"); $question->setLabel("Security question: What color is a green apple?"); $question->setRule("required")->setCustomMessage("Please answer the security question"); $question->setRule('compareTexts', ["green", "it's green", "the color green"])->setCustomMessage("Answer is not correct!"); $question->setSuccessMessage("Answer is correct!"); $form->add($question); This way you can completely customize your field like any other input, including error and success messages ?1 point
-
Thanks for the responses, guys. After a bunch of back and forth with Dreamhost, I ended up asking them to move us to a different web VPS and MySQL VPS. After they did that, the problem disappeared! Still not sure exactly what the issue was (my GUESS is either a network issue or another VPS on the same hardware causing an issue), but glad we got it figured out.1 point
-
I do it usually as follows: 1.) Create a file /site/translations.php <?php namespace ProcessWire; /** * TRANSLATABLE STRINGS * Define globally available translatable strings * * USAGE * place this file under /site/translations.php * __("My translatable string", $ferry); * The wire property $ferry refers to the textdomain of this file * */ __("My translatable string"); 2.) Define a wire derived object and place it in /site/ready.php /** * TRANSLATABLE STRINGS * Include translatable strings * @see /site/translations.php * @var $ferry */ $this->wire('ferry', '/site/translations.php', true); output in any template /** * output in template */ echo __("My translatable string", $ferry); Now you need to translate it only once, by using the string in any template. Usecase: strings like "read more" etc. For strings specific to a template you can use simply: /** * output in template */ echo __("My translatable string");1 point
-
I've been using PW for quite a while, now, so I would like to give back to the community that helped me so many times. I had this customer that wanted to use the Google Translate API to automatically translate the site, so I built this function that takes advantage of it without the need to use the API on every page cycle. I put it on a file that gets called on the _init.php, so that I can use it on every template. Here it is: <?php function googleAutoTranslate($page, $field) { // Turn off outputFormatting $page->of(false); // Get current language and field content for this language $current_language = wire('user')->language->name; $field_content = $page->getLanguageValue($current_language, $field); // Is there any content for this language? if($field_content != '') { // Do nothing! } else { // No content, lets translate... // Get default language text $text = $page->getLanguageValue('default', $field); // Translate only if there's content in the default language if($text != '') { // Translate it $apiKey = 'YOUR API KEY HERE'; $default_language = 'pt'; // Your default language here! $url = 'https://www.googleapis.com/language/translate/v2?key=' . $apiKey .'&q=' . rawurlencode($text) . '&source=' . $default_language . '&target=' . $current_language; $json = json_decode(file_get_contents($url)); $field_content = $json->data->translations[0]->translatedText; // Save translated text $page->$field->setLanguageValue($current_language, $field_content); $page->save(); } } // Turn on outputFormatting $page->of(true); // Return result return $field_content; } ?> Whenever you use a field on a template that should be auto translated, just call the function with a page object and the field name, like so: echo googleAutoTranslate($page, 'body'); Features: Translation occurs only once per field, so you don't need to keep paying translations (it stores the translation into the field language); You can correct the translation in the admin area and it won't be overwritten; If you need the translation to be made again, just delete the field content in the needed language. For the translation to occur, content must exist in the default language. I had to fight a little to get this working, so I hope this helps anyone, who comes across this particular need. Nice Things To Have If someone wants to give it a shot to make this into a module, please do. It would be nice to have a checkbox "Enable Google auto translate for this field", when you edit a field input features. Don't Spend Too Much Mind you that the Google translate is a payed service! and needs a Credit Card to get it going (even with $300 free credit); With a relatively small site (and the tests made to get this to work) I already spent about 80.000 translated characters = $3, Hope this helps someone!1 point