Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/27/2020 in all areas

  1. Here's a small new module that started as a spinoff of a memcache proof-of-concept. Cache your strings and partials in-memory using Redis as a backend. CacheRedis All you need is a running Redis database. The module supports connection through regular TCP, over TLS and via unix domain sockets. Host and port are configurable, and authentication is supported too. Here's a screenshot of the module configuration options: I'll not go into too many details about the usage, you can see everything explained in the README on GitHub, and just highlight the most important points. When the module is active, you'll have a wired $redis variable, which means you can reach the module as $redis, wire("redis") or within Wire classes / modules as $this->redis. CacheRedis is strongly influenced by WireCache, and its usage is (hopefully) straight forward. // Store an entry in the cache under the given key name with the given value: $redis->store("cached_value_number_one", $expire, $value); // Retrieve a value from the cache $value = $redis->fetch($key); // Delete a cache entry $redis->delete("my_other_cached_value"); // Clear the whole cache $redis->flush(); // Retrieve a value from the cache, and if not found, create it through the given function // and store it with a lifetime of 5 minutes (300 seconds) $value = $redis->fetch($key, 300, function() use($page) { return "Page last changed on " . strftime('%m/%d/%Y %H:%M', $page->modified | $page->created); }); // Render a file using wireRenderFile and store it in the cache. // We'll pass a selector as the expiry value so this cache gets // emptied every time a page matching the selector is saved. $news = $redis->renderFile("partials/news.php", 'template=blog-post', ["page" => $page]); The module is still very crude work in progress, but I hope some of you feel daring, try it out and let me know in case anything breaks. Have fun!
    5 points
  2. @ryan many thanks for that useful piece of code. I used it a lot lately, also on sites that changed during my locally work. Therefor I need to adapt it a bit to first check if the remote file is available (and the optional use of basic auth). So, if it is of use for someone too, here it is: // use assets from remote host on demand for local development copies $wire->addHookAfter('Pagefile::url', function($event) { fetchRemoteAssetsToLocalDev($event); }); $wire->addHookAfter('Pagefile::filename', function($event) { fetchRemoteAssetsToLocalDev($event); }); function fetchRemoteAssetsToLocalDev($event) { if(!$event->wire('user')->isSuperuser()) return; // only my personal preference $config = $event->wire('config'); if(!$config->Remote2Local) return; // I set the domain name of a remote host in the site/config.php $remoteHost = 'https://' . $config->Remote2Local; // I always use https these days $file = $event->return; if('url' == $event->method) { $file = $config->paths->root . substr($file, strlen($config->urls->root)); // convert url to disk path } if(!file_exists($file)) { // download file from source if it doesn't exist here, but exist on source $src = $remoteHost . '/site/assets/files/'; $url = str_replace($config->paths->files, $src, $file); $http = new WireHttp(); if($config->Remote2LocalBasicAuth) { // optionally use basic auth with credentials from config.php $http->setHeader('Authorization', 'Basic '.base64_encode($config->Remote2LocalBasicAuth)); } // check if file exist on remote host $http->head($url, [], ['use'=>'curl']); if('404' != substr($http->getHttpCode($url), 0, 3)) { // file is available if($config->Remote2LocalBasicAuth) { $http->setHeader('Authorization', 'Basic '.base64_encode($config->Remote2LocalBasicAuth)); } $res = $http->download($url, $file, ['use'=>'curl']); } else { // file is missing, log it $event->wire('log')->save('remoteFetch404', $url); } } } // use assets from remote host on demand for local development copies
    2 points
  3. Bootstrap-4 Minimal site profile for ProcessWire This profile is based on the "minimal site profile (intermediate edition)" and bundled with Boostrap v4.4.1 Features Bootstrap SASS Font-Awesome SASS Render / helper functions for : Simple ul navigation Bootstrap Multi-level navbar Bootstrap Carousel Bootstrap Cards Bootstrap Jumbotron Boostrap Accordion Assets minification, files bundle Dependencies jQuery Popper.js Bootstrap FontAwesome Prequisites You'll want to install the following on your system before proceeding: Yarn / NPM How To Install Download the zip file at Github or clone directly the repo with git clone and skip the step 2. Extract the folder site-pwbs4-master into a fresh ProcessWire installation root folder. During the installation of ProcessWire, choose the profile "ProcessWire Bootstrap 4 profile". After installation You can find the development file (CSS/SCSS/JS) in site/assets/dev/src The profile can be used as is only with $config->debug set to false. To use it in debug mode, you are required to install the dependencies with the package manager. Open a terminal in site/assets/dev and execute the following command-line: yarn Available commands : Rebuild, minify and bundle assets for release : yarn build References Bootstrap v4 documentation ProcessWire documentation ProcessWire Forum: bootstrap tag ProcessWire Forum: bootstrap related posts Credits The ProcessWire staff Inspiration from @gebeer and his Bootstrap 3 profile post Members who contributed in various post about Bootstrap navigation and code (see code-source for refs). Screenshots
    1 point
  4. @Macrura Are you doing a search of some sort? i.e. using a selector? A field name like author_images_randomgibberishstring sure looks strange. Did you name it like that? In "regular" image fields I found the new feature works just fine, also with multi-language. Maybe you are using an image field inside repeaters?
    1 point
  5. @ukyo showed me this awesome uikit pagebuilder for wordpress: https://demo.yootheme.com/themes/wordpress/2019/balou/wp-admin/customize.php This link might also be interesting for you @Jonathan Lahijani
    1 point
  6. Thanks @bernhard, I updated module with same finder function used on FontIconPicker module. I am using dirname function for getting module or templates folder names from file path. "Example : Dive" is title of config, "(mystique)" is name of module folder
    1 point
  7. hi @ukyo replying to this comment: https://processwire.com/talk/topic/8960-fieldtypefonticonpicker/?do=findComment&comment=198140 It's definitely the glob() that's causing the problem. These are the paths created by your module: I wanted to fork your next branch, but github throws a 500 error when forking at the moment. But I'm not able to fix it anyhow, because I don't understand your code. This is what I have so far: /** * @inheritDoc */ public function ready() { $paths = []; $paths[] = __DIR__ . "/configs/"; $paths[] = $this->wire("config")->paths->templates . "configs/"; bd($paths); foreach($paths as $path) { $opt = ['extensions'=>['php']]; foreach($this->wire->files->find($path, $opt) as $file) { bd($file); // $dirname = dirname(dirname($file)); // $base = strtolower(str_replace([dirname(dirname(dirname($file))), "/"], "", $dirname)); // $name = str_replace([dirname($file), "/", "Mystique.", ".php"], "", $file); // $this->resources[$base][$name] = $file; } } } I don't understand what you are doing with all those dirname() basename() calls... Maybe you want to use pathinto() instead? bd((object)pathinfo($file)); Looking forward to finally testing your module ?
    1 point
  8. this is an amazing case study.. thanks for sharing with us
    1 point
  9. Give this a try: // Create WireUpload instance (it doesn't matter what name you give it) $wu = new WireUpload('foo'); $file_path = '/the/path/to/your/image.jpg'; // Get the basename only $basename = basename($file_path); // Sanitise basename the same as would be done if the file was uploaded via admin $sanitised_basename = $wu->validateFilename($basename); // Look for an existing file with that sanitised basename $existing_file = $page->images->get($sanitised_basename); // Add the file if it doesn't exist if(!$existing_file) $page->images->add($file_path);
    1 point
  10. In accordance with the gist identified by Kongondo, I’ll comment that I figure most of the complexity will probably lie in your envisioned front-end. I’m certain that PW will work just fine as far as it is concerned, but it won’t help you any displaying a zoomable map and all that. This is an ambitious project if you’re really going to involve native mobile apps and payment processing. I would probably suggest keeping it simple for now, and just worry about getting your data from the user to your database and back. Working with data and users is pretty much a breeze with PW. While there may be more suitable products for your particular use case (you’d have to ask someone more broadly versed), I wouldn’t worry about the ProcessWire side of things too much. It’ll probably the part you’ll need the least help with. My tip would be to look into front-end people if you really are looking to hire. I should mention that my personal MO online is Hemingway-inspired, i.e. post drunk, browse sober, and right now I’m, like, really posting.
    1 point
  11. Almost every time I find one of these interesting ML/AI/Science based Python projects I want to include in my own work, I run in major compatibility issues. Either a bound C library has changed its signature too much, or the Python lib never got adapted to version 3 (or 3.7 and another lib needs native types). To me it seems like Python is partly a graveyard of university projects nobody cared to continue. Not that Python is bad in general. When Google app engine support for Python came out I implemented a service together with two other devs (extending in-game functionality of a virtual world) that took up to a few million hits per day and was lots of fun to build. But developing in Python can easily become a package version nightmare, and most tutorials out there just ignore that, which adds a steep learning curve if you want to do complex projects in Python. pyenv and pipenv, which came out last year, only address parts of that. This xkcd is quite fitting I think ? I for one also have a (subjective) aversion to languages where whitespace has too much meaning. If you ever learned Cobol, you probably know what I mean...
    1 point
  12. In an ongoing effort to provide a sort of case study, and more info about this, I'll post random screens and info about the various features of this site. (1) Custom Dashboards The site uses a custom module that supports multiple dashboards. Any given dashboard is configurable and access controlled also. This is the main dashboard: (2) The admin editor pages take advantage of some great modules, namely RuntimeMarkup @kongondo, PageFieldInfo @Robin S, Field Descriptions Extended and more, There is also a new module not released yet called Admin Comments, which for this project got a lot of use. When dealing with a large and complex data collection as was the case with this project, the editors benefited from the ability to have the data auto-analyzed on each work so the "auto flags" field helped with that. The comments also allowed editors to post information, ideas and comments right into the page editor. The AdminComments module also provides the option for any posted comment to be emailed to the other team members (selectable), and the notification email (which is customizable) allows the recipient to click directly to the editor for that page. This saved incalculable hours of work, and enhanced communication during the project, across this large data set.
    1 point
  13. Just tried tailwindcss as base stylesheet for mpdf ? <?php require_once __DIR__ . '/vendor/autoload.php'; $mpdf = new \Mpdf\Mpdf([ 'defaultCssFile' => 'css/prod.css', 'format' => [190, 236], 'orientation' => 'L', 'default_font' => 'arial', ]); $mpdf->WriteHTML('<h1 class="text-center bg-blue-700 text-yellow-200 mx-64 py-2 font-extrabold text-3xl rounded-full">Hello world!</h1>'); $mpdf->WriteHTML('<svg class="stroke-current text-purple-500 inline-block h-12 w-12" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="8" cy="21" r="2"></circle> <circle cx="20" cy="21" r="2"></circle> <path d="M5.67 6H23l-1.68 8.39a2 2 0 0 1-2 1.61H8.75a2 2 0 0 1-2-1.74L5.23 2.74A2 2 0 0 0 3.25 1H1"></path> </svg>'); $mpdf->WriteHTML('<div class="my-10 bg-red-100 border border-8 border-red-400 text-red-700 px-12 py-3 rounded relative" role="alert" style="border: 1px solid red"> <strong class="font-bold">Holy smokes!</strong> <span class="block sm:inline">Something seriously bad happened.</span> <span class="absolute top-0 bottom-0 right-0 px-4 py-3"> <svg class="fill-current h-6 w-6 text-red-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>Close</title><path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/></svg> </span> </div>'); $mpdf->WriteHTML('<hr class="my-2">'); $mpdf->WriteHTML('<div class="bg-indigo-900 text-center py-4 lg:px-4"> <div class="p-2 bg-indigo-800 items-center text-indigo-100 leading-none lg:rounded-full flex lg:inline-flex" role="alert"> <span class="flex rounded-full bg-indigo-500 uppercase px-2 py-1 text-xs font-bold mr-3">New</span> <span class="font-semibold mr-2 text-left flex-auto">Get the coolest t-shirts from our brand new store</span> <svg class="fill-current opacity-75 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z"/></svg> </div> </div>'); $mpdf->WriteHTML('<div class="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4" role="alert"> <p class="font-bold">Be Warned</p> <p>Something not ideal might be happening.</p> </div>'); $mpdf->WriteHTML('<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full"> Button </button>'); $mpdf->WriteHTML('<div class="max-w-sm rounded overflow-hidden shadow-lg"> <img class="w-full" src="/img/card-top.jpg" alt="Sunset in the mountains"> <div class="px-6 py-4"> <div class="font-bold text-xl mb-2">The Coldest Sunset</div> <p class="text-gray-700 text-base"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatibus quia, nulla! Maiores et perferendis eaque, exercitationem praesentium nihil. </p> </div> <div class="px-6 py-4"> <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2">#photography</span> <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2">#travel</span> <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700">#winter</span> </div> </div>'); $mpdf->Output(); At least for paddings, margins, text-alignments and colors this could also be helpful. It seems borders do not work - the red border is done manually via "1px solid red" style rule.
    1 point
  14. I realize this is an old module, and RSS is hardly new sexy stuff, but RSS feeds are a great "glue" between products. Im trying to get an RSS feed out of a PW site and did the following steps: Turned on the Module from Core. Left all module options default. Copied example code into a new file called rss.php in my /site/templates directory. changed items to get a page by ID: $items = $pages->get(111)->children(); In ProcessWire, went to add a new template, selected the rss file. Left the template blank with no fields. Created a new page with RSS template. Viewed page and got no output—visibly blank, and view source is an empty line. I'm probably tripping over my own shoelaces here, but thanks for any advice.
    1 point
  15. If you're not harnessing the backend from ProcessWire I'd personally tend to not use ProcessWire. While it's entirely possible to do so (maybe also search for prev. discussions on the topic) there are some parts, which in my opinion discourage that kind of usage: Lack of proper testing capabilities. There are topics on how to do TDD with processwire, but the options on managing db state or handling requests in tests are not there. If you need to manage a lot of diverse data the autoloading of every template/field on each request can become a bottleneck. Working around it by reusing more fields/templates can work, but isn't great either. The selector engine for pages is great for light to medium complex stuff, but complex selections and especially aggregations need custom SQL or third party solutions like RockFinder. Also if you're not careful it's tempting to fall into n+1 query problems with fields / relationships being lazy loaded by default. Transactions are hardly used by the core, so if you want/need to prevent partial updates from happening you need to ensure that on your own by wrapping stuff into transactions. Not to say ProcessWire isn't otherwise a nice system, but those are the things I'd urge anyone to evaluate before using ProcessWire in a web application project.
    1 point
  16. Thanks Robin, this worked well and avoids the approach of having to hack PW and make InputfieldPage::getPageLabel hookable. Note: In order for it to work, you must edit the field's "Label field" under the "Input" tab. It must be changed from "title (default)" to "Custom format (multiple fields) ..." and a value must be put in the "Custom page label format" field, even if it's just a temp value (I put "x").
    1 point
  17. took me some time today to find out why my page was not showing up... i ended up creating a hook that does what apeisa had in his mind some years ago // set all languages active automatically $wire->addHookAfter('Pages::added', function($event) { $page = $event->arguments(0); foreach ($this->wire->languages as $lang) $page->set("status$lang", 1); $page->save(); }); does anybody see any danger in that? i'm not so experienced with multilang yet... edit: somehow it seems that ->setAndSave(...) does NOT work in this situation. @Can or @dragan can you confirm that?
    1 point
  18. There is one thing that needs a bit attention when importing data. We need to check if a record was also imported by a previous run of the script, otherwise you may end up with numerous duplicates. while($row = $result->fetch_assoc()) { $title = wire("sanitizer")->text($row['title'], array("maxLength"=>128)); // fetch and sanitize the title $p = wire('pages')->get("title={$title}"); // check if it already exists if(0 < $p->id) continue; // move on to the next record if it exists $p = new Page(); $p->template = "dam"; $p->parent = "something"; $p->title = $title; // use the sanitized title $p->save(); }
    1 point
  19. Hi Tony! Welcome to the forum I think one of the fundamental things to consider with projects like these, is to actually look and analyse the existing data - the structure, the format, the quality, and any relationships there may be. It's almost going through the normalisation process but perhaps not as strict. It would be a good idea to take every column in the existing database to decide how that will be represented in the ProcessWire site. Probably, some of these will be simple translations - Varchars will become Text fields, and Ints will still be Integer fields. But what will be more important is the data in these fields - does it vary with just about every single dam? Is it a value representing Yes/No? Are there only a few values for that column that all dams can potentially use? If so, do the values all use the same spelling of words, or are some mixed case or have weird formatting or spacing issues? When you have a set list of values to choose from, this is where you can decide how to store the data in ProcessWire - Page fields, PageTables, Options field, etc. If your source data quality is good, your job will be easier. If it's not, there will be some work involved in preparing it so that it is clean to work with. You may already have a good idea of how your data looks or is structured, but I usually like to do some form of planning on paper or using a spreadsheet to map out the source data to the ProcessWire templates and fields. Doing the important work now will save you hassle later on down the line and will really help you to make the search feature more functional. As an example: In ProcessWire, I imagine there would be a template created called 'dam'. You might add the following fields to this template (just for starters): title description location (FieldtypeMapMarker) height (integer/float) length (integer/float) capacity/volume (integer/float) country (Page field/Options field?) built (date) opened (date) For each dam, a Page would exist somewhere in the page tree, using the 'dam' template. As you've already seen the Skyscraper profile, you can probably look at that for more ideas on how to structure things though
    1 point
  20. I Would like to throw a huge, hefty spanner into the works here! (Just for fun) If you split PW into two piles, in one pile you have the Site directory. Here is, or will be, your CMS. PW gives you a starter, but once you get into it, you are going to build your own content management structure in there on top of the base. In the other pile is the WIRE directory. However, this is NOT a CMS, or perhaps even a CMF .... I have a suspicion that it is really a CME - a Content Management ENGINE! Joss PS: I have this great want to rename the SITE directory to PROCESS ... just to round off the gag.
    1 point
×
×
  • Create New...