Leaderboard
Popular Content
Showing content with the highest reputation on 03/14/2015 in all areas
-
Update: version 0.0.4 Added 7 permissions to control visibility/access to advanced settings by non-superusers as discussed above. Currently this is only available for testing in Menu Builder dev branch. Note that you have to create the permissions yourself and add them to a role. Please thoroughly read the updated README about how to use these permissions; depending on your situation, you may not have to create any of the permissions. In summary, these control: Locking/unlocking menus (menu-builder-lock) Trashing and deleting menus (menu-builder-delete) Use of selectors to add pages as menu items (menu-builder-selector) Use of markup/HTML in menu item titles/labels (menu-builder-markup) Specifying of PW pages that are selectable as menu items in the page fields AsmSelect and PageAutocomplete (menu-builder-selectable) Editing of nestedSortable settings, e.g. maxLevels (menu-builder-settings) Ability to change the page field (AsmSelect vs PageAutocomplete) to be used when selecting PW pages to add as menu items (menu-builder-page-field) Please test and let me know, thanks.4 points
-
Hello there Yesterday we at update AG relaunched the new 1815.ch news portal of Mengis Medien AG. It's a big new portal of a local newspapers here in Wallis Switzerland. That's where the Matterhorn is also It was a thrill to work on this project using ProcessWire. We're still working out some details and adding more stuff in future. There's a lot going on and it has quite lot of traffic. 60k+ pages at the moment. Currently it serves 18k+ articles plus a lot of other data that are just pages. But will grow a lot. The portal has currently around 7k+ user registered. Lots of imports and exports are going on in the background. That mostly are XML feeds or data being uploaded to server. Some news are imported and automated. While they have different teams creating articles apart from the imports of their newspaper also via XML. http://www.1815.ch3 points
-
Get it from GitHub Setup Just put the module in you modules directory and install it via admin. Intro This module might come in handy if you like to keep your templates clean and free of unreadable and unmaintainable string concatenations and even free of any logic. It also comes with some handy features besides just embedding JS, CSS and image assets, see below. Yikes! <link href="<?php echo $config->urls->templates . 'styles/foo.css'; ?>"> <link href="<?php echo $config->urls->templates . 'styles/bar.css'; ?>"> <script src="<?php echo $config->urls->templates . 'scripts/foo.js'; ?>"></script> <script src="<?php echo $config->urls->templates . 'scripts/bar.js'; ?>"></script> <img src="<?php echo $config->urls->templates . 'images/sky-scraper.jpg'; ?>" alt="Some huge building"> <img src="<?php echo $config->urls->templates . 'images/owzim.jpg'; ?>" alt="Handsome!"> Way cleaner <?php echo $asset->css('foo'); ?> <?php echo $asset->js('foo'); ?> <?php echo $asset->img('sky-scraper.jpg', 'Some huge building'); ?> or with short syntax <?= $asset->css('bar') ?> <?= $asset->js('bar') ?> <?= $asset->img('owzim.jpg', 'Handsome!') ?> And prettier if you're using Twig {{ asset.css('foo') }} {{ asset.css('bar') }} {{ asset.js('foo') }} {{ asset.js('bar') }} {{ asset.img('sky-scraper.jpg', 'Some huge building') }} {{ asset.img('owzim.jpg', 'Handsome!') }} Usage JS example Let's use the js method an its configuration as an example, and assume we have the following files located in /site/templates/scripts - index.js - index.min.js - main.js $config->blick = array( 'jsPath' => $config->paths->templates . 'scripts', 'jsUrl' => $config->urls->templates . 'scripts', 'jsMarkup' => '<script src="{url}"></script>', 'jsDefault' => 'markup', 'jsVersioning' => true, 'jsVersioningFormat' => '?v={version}', 'jsMin' => true, 'jsMinFormat' => "{file}.min.{ext}", ); $asset = $modules->get('Blick'); $asset->js('index')->url; // returns /site/templates/scripts/index.min.js?v=1426170460935 // 'min' and version parameter added, which was fetched from the file modified date $asset->js('main')->url; // returns /site/templates/scripts/main.js?v=1426170460935 // without 'min', because there is no main.min.js $asset->js('main'); // returns <script src="/site/templates/scripts/main.js"></script> // because 'jsDefault' is set to 'markup' // you can also access it explicitly via $asset->js('main')->markup $asset->js('http://code.jquery.com/jquery-2.1.3.js'); // returns <script src="http://code.jquery.com/jquery-2.1.3.js"></script> // nothing is modified here, because it's a remote url You can use the file name with or without extension. Adding a version parameter only takes place, if jsVersioning is set to true, it's a local file and it exists. Modifying the file name to include min only takes place, if jsMin is set to true, it's a local file and it exists. The same applies for the $asset->css('file') method: $config->blick = array( 'cssPath' => $config->paths->templates . 'styles', 'cssUrl' => $config->urls->templates . 'styles', // and so on ... ); IMG example the img method lets you include images, crop and resize them, without them having to be a page image. $config->blick = array( 'imgPath' => $config->paths->templates . 'images', 'imgUrl' => $config->urls->templates . 'images', 'imgMarkup' => '<img {attrs} src="{url}" alt="{0}">', 'imgDefault' => 'markup', 'imgVariationSubDir' => 'variations', ); $asset = $modules->get('Blick'); $asset->img('sky-scraper.jpg')->url; // returns /site/templates/images/sky-scraper.jpg $asset->img('sky-scraper.jpg', 'Some huge building'); // returns <img src="/site/templates/images/sky-scraper.jpg" alt="Some huge building"> // any arguments following the filename are passed as an array // in this case the alt value is the 0th argument, so {0} get's replaced // you can set as many arguments as you want in 'imgMarkup' $asset->img('sky-scraper.jpg')->size(100, 100)->url; // returns /site/templates/images/variations/sky-scraper.100x100.jpg // the resized image is put into a subdir 'variations' as configured in 'imgVariationSubDir' // if 'imgVariationSubDir' is left empty, the variation will be put in the same directory $asset->img('sky-scraper.jpg', 'Some huge building')->attr('title', 'Some huge building'); // returns <img title="Some huge building" src="/site/templates/images/sky-scraper.jpg" alt="Some huge building"> // the resized image is put into a subdir 'variations' as configured in 'imgVariationSubDir' // if 'imgVariationSubDir' is left empty, the variation will be put in the same directory You can also setup predefined variation settings in imgVariations $config->blick = array( 'imgVariations' => array( 'header' => array( 'width' => 960, 'height' => 360, 'options' => array( 'suffix' => 'header', ), ), 'person' => array( // and so on ... ), ), ); And call it like so: $asset->img('sky-scraper.jpg')->variant('header')->url; // returns /site/templates/images/variations/sky-scraper.960x360-header.jpg $asset->img('sky-scraper.jpg')->variant('header', 50)->url; // returns /site/templates/images/variations/sky-scraper.480x180-header.jpg Attributes example Since version 0.4.0 you don't need to create arbitrary variable placeholders, if you want to use attributes only. Now you can use the {attrs} placeholder and set the attributes via $asset->attr('name', 'value'). The name argument can also be multiple names, split by a pipe |. $config->blick = array( // ... 'imgMarkup' => '<img {attrs} src="{url}">', // ... ); $asset->img('sky-scraper.jpg')->attr('alt|title', 'Some huge building'); // returns <img alt="Some huge building" title="Some huge building" src="/site/templates/images/sky-scraper.jpg" > Using files that are not in the configured directory If you want to include files, that are neither in the configured directory nor in one of its sub directores, just use an absolute path (actually, relative to your /site directory. $asset->js($config->urls->SomeModule . 'scripts/file-in-root'); Autoload the module If you don't want to include the module manually via $assets = $modules->get('Blick'); you can set it to be autoloaded under a custom name: $config->blick['autoloadAs'] = 'fiddle'; Now it becomes automatically available in your templates under the name fiddle $fiddle->css('foo'); $fiddle->js('foo'); $fiddle->img('baz.png', 'qux'); Please note, that, if you're using the TemplateTwigReplace.module you will have to add your chosen autoload name to the Auto-import fuel list on the module's config page. See config-example.php for all configurable settings. Change Log 0.5.0 add optional scale argument to variant-method: $asset->img('foo.jpg')->variant('header', 50) 0.4.0 add possibility to get/set and render attributes (see section Attributes example) 0.3.0 add $asset->variant('name') alias for $asset->getVariation('name') 0.2.0 fixes and internal refactorings 0.1.0 initial version2 points
-
I'd like to see better Hanna Code management and I think 4 things could greatly assist. 1 - Tags to be able to tag a piece of Hanna Code in the same manner as we tag templates. We could then see the list of Hanna Codes arranged in the same format as templates. IE broken down by tag. 2 - Usage On the Hanna Code list i'd also like to see a column called Pages (and Templates?) telling me how many pages and templates use my Hanna Code. Again, similar to the Templates layout. 3 - Filter / Find The Find page has a tab called Filters for searching by template, field etc etc. In fact, I can filter by almost anything except Hanna Codes. 4 - Descriptions To be able to add a plain text description to a Hanna Code. I try to name my HCs in a helpful way such as Get-Video Get-Investor-News etc Sometimes I have several variations of the above and I'd like an at-a-glance way to distinguish them without having to click into the HC or at least be able to see the description once I've clicked in. Anyone else feel the same or do I use HC more than most?2 points
-
Not sure why this hasn't been mentioned, so I am wondering if I am missing something relevant, but why not use the $template->noSettings option? Do you need to hide on a page basis, rather than per template? Anyway, if it suits your needs, turn on advanced mode in your config.php file and then you will have a Disable Settings Tab? option on the Template's System Tab. Hope that might help.2 points
-
I have seen that error when fieldtype doesn't match input or a required field is empty, but it generally informs me what field was the problem (with a big old red notice on top of the field too). So that's weird that you're not getting any description of the problem. If you haven't added any of your own fields to the user template and have checked/double-checked the input of every form, here is what I would do : 1. turn on debug in /site/config.php and see if it gives any extra information 2. If that fails, search the code to see where it outputs that error. (Only one place: https://github.com/ryancramerdesign/ProcessWire/blob/676458407bd530b69b50c6ef2f44cf16e4ef4449/wire/modules/Process/ProcessPageEdit/ProcessPageEdit.module#L211) Based on that it's safe to assume you have some formErrors. Look a few lines before that (L195), I would temporarily change $formErrors = 0; foreach($this->notices as $notice) { if($notice instanceof NoticeError) $formErrors++; }to $formErrors = 0; foreach($this->notices as $notice) { if($notice instanceof NoticeError) { $this->error('Notice: '.$notice); $formErrors++; } } That might give you a clue about the notice that is causing a formError. Once you get that info (or even if you don't), you should undo the changes you made to the module file. Anyway it's a hack, but it's how I sometimes investigate what is happening...2 points
-
You should normally not do this, but I'm assuming that you set System on a page that you created, and that you want to remove this setting. The way to do this with the API is to do as follows: // Assuming that $page refers to the page for which you want to remove the status // Enable overriding the system status flags $page->status = $page->status | Page::statusSystemOverride; $page->save(); // Change the system status flags $page->status = $page->status & ~Page::statusSystemID; // If you want to uncheck the first system checkbox $page->status = $page->statux & ~Page::statusSystem; // If you want to uncheck the second system checkbox $page->save(); // Disable overriding the system status flags $page->status = $page->status & ~Page::statusSystemOverride; $page->save(); If it's just to correct a mistake, the more straightforward way to do the change is by modifying the database directly: In the database, find the right page in the pages table (you can find it easily by name or by id, which is indicated in the url when you edit the page). If you want to remove the first system flag, subtract 8 from the value in the status column (so if it's 9, it should become 1). If you want to remove the second system flag, subtract 16 from the value in the status column (so if it's 17, it should become 1). If you want to remove both, simply combine the operations by subracting 24. I hope this helps!2 points
-
Hey, just noticed right now that this is a swiss powered discussion Have a nice weekend! Cheers2 points
-
I opened an issue in the Mobile Detect github space regarding how this module installs. Reference https://github.com/justonestep/processwire-mobiledetect/issues/12 points
-
Get the last version: from PW modules directory: http://modules.processwire.com/modules/fieldtype-select-ext-option/ from Github: Github: https://github.com/kixe/FieldtypeSelectExtOption From the first view a simple select dropdown Fieldtype. But what is different? Rather than the option field in the modul settings you will find some setting fields to define a source (datatable or field) from where you can pull the options (value and label). I found this very useful when I had to put 250 options in a select field (which I provide in frontend too) and needed this connected and congruent to another more complex table. So now I can make changes in the main table and the select field will take over these changes. You can define the following in the settings: datatable tablecolumn for (value) should be integer tablecolumn for (label) dependance (value or label) order ascending or descending Here we go: https://github.com/k...electExtOption/ (updated 10.03.15 Version 1.0.2 with Multiselect Option) (updated 11.03.15 Version 1.0.3 with Select Inputfields in Settings)1 point
-
In your foreach gallery loop you are creating many lightboxes with the same ID: <a href="#gallery" class="lightbox" id="image_gallery"> ID's should be unique, only one per page is allowed with the same name. Try something like // before the loop: <?php $counter = 1; ?> // in the loop: <?php $currentID = "image_gallery_" . $counter; ?> <a href="#<?php echo $currentID; ?>"> <a href="#gallery" class="lightbox" id="<?php echo $currentID; ?>"> <?php $counter++; ?> Then you will have IDs like "image_gallery_1", "image_gallery_2", etc.1 point
-
There must be recent changes I guess, but this one works: oops this one is for delete tab <?php class AdminHelperHooks extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'My Admin Helper Hooks', 'version' => 1, 'singular' => true, 'autoload' => true ); } public function init() { // add hook to the page edit module and the method that creates the wanted fieldset $this->addHookAfter('ProcessPageEdit::buildFormDelete', $this, "removeDelete"); } function removeDelete(HookEvent $event){ // $event->return being the inputfield wrapper $wrapper = $event->return; // set the inputfield wrapper to hidden $wrapper->collapsed = Inputfield::collapsedHidden; // Get the active Object (ProcessPageEdit) $process = $event->object; // Remove the Settings tab with the ID $process->removeTab('ProcessPageEditDelete'); // we're done } } For settings tab <?php class AdminHelperHooks extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'My Admin Helper Hooks', 'version' => 1, 'singular' => true, 'autoload' => true ); } public function init() { // add hook to the page edit module and the method that creates the wanted fieldset $this->addHookAfter('ProcessPageEdit::buildFormSettings', $this, "removeSettings"); } function removeSettings(HookEvent $event){ // $event->return being the inputfield wrapper $wrapper = $event->return; // set the inputfield wrapper to hidden $wrapper->collapsed = Inputfield::collapsedHidden; // Get the active Object (ProcessPageEdit) $process = $event->object; // Remove the Settings tab with the ID $process->removeTab('ProcessPageEditSettings'); // we're done } }1 point
-
I'd like to resize some images on demand, that are not page images, so they are not attached to a page. How to use the ImageSizer class? I could browse through the code but perhaps someone who used this, could provide some lines of example code. I basically want to pass the image path and cropping options. Are the cropped images saved somewhere if they are not page images, or will the cropping be executed every time? Thanks!1 point
-
@Peter - how many hanna codes do you usually use on the average site? My usage has been maybe 4-5 hanna codes on a site, or maybe as many as 10 on a really complex/large site; I do think maybe tags could help here on this page in terms of organizing them, but also i don't expect my clients to be interacting with the hanna codes list so this would be more of an admin convenience. sounds trickier than the templates, b/c the hanna codes are used randomly within text areas, or text fields - and are processed at runtime to the output; not that it would be impossible, but it might be a process that needs to run to collect all of that data and could take a lot of processing depending on the # of pages in the site.. I do agree some module to get a "hanna code report" than could generate and be able to process something like 50-100 pages at a time before generating the entire report; this could be very useful, because we might want to see where a particular one is being used; personally I always try and come up with solutions that avoid hanna codes if at all possible and are equally easy and potentially more elegant, and as such i never have more than a handful of hanna codes per site; Perhaps some of your hanna codes could be replaced with other solutions? they are always sort of a risk being that they are inserted into RTE, so not as bulletproof as something like a validated text input.. I always provide complete documentation for all hanna codes including the code itself that can be copied and then usage instructions, using my docs and docs tab system, as well as often inline using the Markup Textareas, so from the end user perspective, they can use any available hanna code right on the page (or also input with the helper module); but i do think that having a description field would be handy, especially if you come back to a project after some time, you could see more easily what each one does, at a glance..1 point
-
Glad it solved your problem. Indeed, it's a pretty Swiss thread Though Swiss German would be a little difficult, I'm from Geneva... German would be fine1 point
-
1 point
-
this is embarrassing, because i checked the code for errors but i cant see this! My "Syntax View" is not so good right now, but it gets better. Now, I've removed the "!" from: if (!$this->user->name === 'selina') and now, processwire takes the selected css file! It does what it should do Very nice, thank you1 point
-
That's the way I handle this stuff. It's quite easy with the API to loop through all the fields ($fields->find(type=Image|File)) and set the noLang to true. Don't forget to save(). I'm on mobile so no code example, but let me know if you want an actual example.1 point
-
i don't understand most of what you are talking about - BUT: i understand most of what i am doing with processwire thats what i love about processwire! you don't "see" things that you don't understand and therefore don't need to see. that starts with the admin-interface treeview and continues when you start looking to the file system and furthermore into the code. i just wanted to point out that for a non-professional coder like me these are really important benefits! i like the way PW addresses also beginners and at the same time makes it possible to dig deeper into it if you want to and if you are ready! not before. that said from someone who has created his first hooks some days ago ps: of course i also love discussions like this one on the forum reading about things that i can maybe think of some day.....1 point
-
pages_id is not a column in pages, I think you are looking for 'id'. Results for query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='pages'): +-------------------+ | COLUMN_NAME | +-------------------+ | id | | parent_id | | templates_id | | name | | status | | modified | | modified_users_id | | created | | created_users_id | | sort | +-------------------+1 point
-
We've now added cache busting for all assets in our boileplate. This means that in production, if an asset has been added to a manifest in the assets/ folder, your site will now serve an MD5'd version of the file. i.e. style.css -> style-18925h5bsdfsdfn.css No worries about appending query strings or force refreshing to get the latest asset, it's all done for you. Use of the manifest is optional. If an asset is not being rev'd in the manifest, it will be served with the filename you provide. e.g.: <!-- if this asset is not in the manifest, it will be served as assets/img/logo.svg --> <link rel="logo" type="image/svg" href="http://<?= $config->httpHost . $this->assets('img/logo.svg') ?>"/> <!-- if this asset IS in the manifest, in production it will be served as assets/css/style-9n183he.css --> <link rel="stylesheet" type="text/css" href="<?= $this->assets('css/style.css') ?>" > For an asset to be eligible for rev'ing, it must be accessed through the assets helper in views / templates: $this->assets('path/to/my/asset.ext') This is used best in conjunction with some sort of task automation, for which we have a Yeoman generator which generates a project with a Gulpfile that handles all the rev'ing of assets without any additional work for you: https://github.com/fixate/generator-fixate-pw (and more specifically, the gulpfile: https://github.com/fixate/generator-fixate-pw/blob/master/app/templates/_gulpfile.coffee) To create the manifest, you can run the following from the command line: $ gulp build You're now ready to deploy with your cache busted assets. Assets that are being rev'd by Gulp are css, js, images, and fonts (even handles rewriting paths in your css). Happy cache busting!1 point
-
I know there are benefits and drawbacks to different approaches, so I'll try to explain why PW uses the approach it does, and respond to some of the points above. The approach described as an alternative here is similar to what I've used on other projects, including PW1. I was really looking to come up with something different for PW2. The goal was to make it as absolutely simple as possible for people to add hooks and for people to make methods hookable. I wanted it to be in the background and everywhere, so that you really didn't even have to think about it. It's not designed for ease of consumption by xdebug, I'll give you that. But it is designed for ease of consumption by you and me, which I consider more important. Admittedly I don't use xdebug very much anymore, so designing things for xdebug has not been a priority. When you start a new CMS project, you are in a crowded space, so you have to come up with things that are different. So one of the ways ProcessWire differentiates itself is by making hooks easier to hook into and create than they are in other platforms, and I'd like to keep to that. When it comes to PW's code base, I consider it important to not add complexity purely for sake of static analysis. From my perspective, static analysis is a good thing, and I'm more than happy to let it dictate the direction of comments and what supports the code. But when it starts to dictate the direction of the actual code towards unnecessary complexity/verbosity, less efficiency or reduce the simplicity of the API, then I consider it no longer helpful. If ProcessWire were just a PHP framework and coders in IDEs were the primary audience, then I would feel differently. But for ProcessWire's audience and growth, when I'm confronted either making my IDE happy (and related tools like xdebug), or making the API (or related things like hook system) as simple and as good as they can be, I'm always going to choose what's best for PW's API and systems. My preference is making both happy. But when you are doing something different, existing tools won't always be familiar with it. For something like the hook system, there was definitely a conscious decision to go with what's best for PW and PW users, over what's best for static analysis or xdebug. All the add hook methods are actually handled by just one method: addHook(). The point of the other methods (mentioned below) is to make things simpler for you, and make your code more readable. I prefer verbose method names to boolean and array arguments because they are self describing. think this is a benefit, not a drawback. Use addHook() if you want to add a method to a class that isn't already there. Use addHookProperty() if you want to add a property (rather than a method) to a class. Use addHookBefore() if you want to hook before an existing method (and have the option of modifying arguments sent to it). Use addHookAfter() if you want to hook after an existing method (and have the option of modifying the return value). Regarding the distinction of hooking a class name or an object, this is also meant to be a help to you: The purpose of being able to call a hook on a class name is so that you can hook ALL instances of that class (current and future). The purpose of being able to call a hook on an object is to hook only that single instance of the object. As for ease of finding hooks, this is also something I've tried to make as simple as possible by using a convention that you won't see elsewhere in ProcessWire: 3 underscores prepended to a method. So while you can use CaptainHook, I'm not sure you need to, because you can find all hookable methods in ProcessWire simply by doing a search for 3 underscores "___". A recursive grep is one easy way to accomplish that. Page::render() is actually a very unique case that you won't see elsewhere in PW (that I can think of). Usually I would have just put a method like that directly in a class and have it handle the render from there (or have the method there to call up the PageRender module). But PW started out as fully API driven, where there was no such thing as "render" of anything, to the core. So the ability to "render" anything was seen as something specific to the web context of a CMS. That's ProcessWire now, but its roots are pure CMF. Today, I would likely just put that render() method directly in the Page class. But I also don't see any reason to move what's already working there, as it really makes no difference in how it works. And you can still hook Page::render if you want to, just like it actually did exist in the Page class. Because you can't actually see a Page::render() method in the class, we use phpdoc at the top of the file for it. I would love to make everything hookable, but the reality is that there is a little overhead associated with every hook (in any hook system). So I don't usually make methods hookable unless there is a request for it to be. We started with very few hooks, and now we have quite a lot. But the majority of the hookable methods you see in PW today are the result of people asking for them to be hookable. And luckily, it's very easy to do just that: just append 3 underscores, and you are done. I would answer this pretty much the same way as the Hookability point above. When more granularity is needed somewhere, we add it, and there's lots of examples throughout the core. But it's hard to know where one might need that until it is asked for somewhere specific. When a module like ProcessPageEdit was originally written, I honestly didn't know if anyone would ever want to hook anything in it at all. Over time, it has become more granular, and over more time will become even more so I'm sure, but only when specific needs for granularity/hooks come up. I love flexibility, but I also love efficiency. If everything in ProcessWire was fully granular and hookable PW might be very flexible for someone looking to hook specific things, but it would also be bloated and slow. My preference is to make specific things more granular and hookable when it will solve someone's specific need. Granted, there are plenty of hooks in PW already that nobody is using, but they are generally in places where it makes no difference in terms of efficiency. I'm not suggesting that hooks aren't efficient – there's very little overhead from hooks. It's just that if you multiply a very little overhead over thousands or hundreds of thousands of calls, then it becomes something. Are there any examples? I've tried to cover all potentially useful state changes with hooks, even if they aren't actively used. For instance, see the large set of hookable methods at the bottom of the Pages class. You'll see similarly named methods in any core class that deals with state changes (like Fields and Templates for example). Though it's also possible I've misunderstood what you mean.1 point
-
Hmmm... I wonder if it's the inline function. Try this code instead for each module: <?php class CustomLogout extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Custom Logout', 'summary' => 'Redirects to a custom login page after logout', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookAfter('Session::logout', $this, 'hookAfterLogout'); } public function hookAfterLogout($event) { $this->session->redirect($this->pages->get('/login/')->url); } } <?php class SiteHider extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'SiteHider', 'summary' => 'Hide Sites in CSS per User Roles', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookBefore("ProcessPageList::execute", $this, 'hookBeforePageListExecute'); } public function hookBeforePageListExecute($event) { if (!$this->user->name === 'selina') $this->config-styles->add($this->config->urls->templates . "css/sitehide.css"); } } Also, be careful with where you put the semi-colons (. In SiteHider, you had put it just after the if, which is a problem.1 point
-
I never liked programs/software translated to Dutch. So personally I wouldn't use the translated ProcessWire. On the other hand, I do think it's good for the ProcessWire project. Could you phone me so we can work something out?1 point
-
Hi guys, I'm impressed with all this information I'm very happy with this! The project is not for now it is for this summer! But I have an idea how can started, and have a few questions to ask the fitnesscoach about sorting, etc. PS: I can not enough saying that your very helpful people and I think this make the PW community very strong and popular! I very very very happy I find PW when I searching for the best CMS A happy (junior) PW-user, Christophe1 point
-
I just committed big refactoring to Fredi, which fixes all the known bugs and simplifies a code a lot. I haven't tested this yet on other pw versions than latest dev, so be careful when testing. It "should" work pretty universally, since now it uses ProcessPageEdit instead of own custom processes. So image/file uploads and reordering (tested) and repeaters (not tested...) should work also.1 point
-
I had a realization recently about the PW data-model that I would like to share. The PW model is actually very akin to that of the Entity/Component model. Pages can be seen as Entities, and Fields can be seen as Components of those Entities. Templates can be seen as Component Types. One important difference from the E/C model, in terms of implementation, is the shape of the resulting entities - Fields are mapped directly onto Pages; or in other words, Component properties are mapped directly onto Entities, which means the Components themselves are limited to a single property at the model-level, even though some Field types are backed by tables with more than one property value, e.g. more than one data-column. I can't help thinking the resulting model is really close, but one step removed from being anywhere near as powerful as a real E/C data-model. To explain why I feel this way, here's a very simple case example. Let's say you have a shop with different types of products, many of which have at least one thing in common - they have a unit price, product title, and manufacturer name. With the PW model, I will add these three fields individually to every Template that describes a product type, and I will address these as, say, $page->price, $page->title and $page->manufacturer. Fetching these three fields requires three joins to separate tables. Conceptually, these three fields are meaningless on their own - they belong to a single component that defines the necessary properties required for something to "be" a product in our system. The, let's say, shopping cart service, for example, is dependent on the presence of all of these three fields and doesn't function if one of them is missing. With the Entity/Component model, instead of adding three individual fields, you define a component type that defines these three fields. You would address them as, say, $page->product->price, $page->product->title and $page->product->manufacturer. In other words, these three fields, which belong together, are exposed in the model as a single, integral component. Fetching these three fields requires a single join to one table. The ability to group together related properties in components has performance advantages (fewer joins/queries) but more importantly, it has practical advantages in terms of programming. You wouldn't need to group together related fields by prefixing them with "name_" anymore, which seems like an unnatural way to create a kind of "pseudo component". Adding/removing properties to a component property would naturally propagate that change to every entity that uses that component, rather than having to run around and update them manually. Controllers/services could define their requirements in terms of component shape. I realize it's a pretty substantial departure from the PW data-model, but perhaps something to think about for an eventual future 3.0. Or perhaps just an idea to consider for a different CMF in the future. Or perhaps just something interesting to think about and do nothing1 point
-
Funny how all problems listed here annoyed me and others too, we get used to them and don't complain. That might even be dangerous, so client's feedback is key.1 point
-
This is what is the most and big point of this awesome community here. There is no huff and saying - we have the best CMS so your problems are no problems - so live with them... Here is instant writing and thinking - we have the best CMS so there must be one/more ways to get this problems away... Thank you Peter for this threat - i discovered AdminCustomFiles while reading your write-up. Best regards mr-fan1 point
-
That's an interesting analogy, although it's not quite the same. Graph databases can co-exist with mysql (a lot of people are using it that way), so its only an extension (maybe a core module) rather than a complete re-work. I'm not sure if anyone has seen neo4j's model. It's exactly like processwire! (http://neo4j.com/developer/guide-importing-data-and-etl/) Check out the part where it talks about the Graph Model. It says: A row is a node A table name is a label name Now this sounds familiar, doesn't it? In processwire's model: A row is a Page A table name is a field name Whoa! Looks like Ryan built a graph model in a relational database - absolutely brilliant! And that's not it, you can use Page fields to create connections between pages (much like creating connections between nodes to form a graph). Also, it's interesting to see the php implementation of neo4j, which also, coincidently, is very similar to processwire's API calls (https://github.com/neo4j-contrib/developer-resources/blob/gh-pages/language-guides/php/neo4jphp/index.php). $app->get('/graph', function (Request $request) use ($neo4j) { $limit = (integer)$request->get('limit', 50); $queryTemplate = <<<QUERY MATCH (m:Movie)<-[:ACTED_IN]-(a:Person) RETURN m.title as movie, collect(a.name) as cast LIMIT {limit} QUERY; $cypher = new Query($neo4j, $queryTemplate, array('limit'=>$limit)); $results = $cypher->getResultSet(); $actors = []; $nodes = []; $rels = []; foreach ($results as $result) { $target = count($nodes); $nodes[] = array('title' => $result['movie'], 'label' => 'movie'); foreach ($result['cast'] as $name) { if (!isset($actors[$name])) { $actors[$name] = count($nodes); $nodes[] = array('title' => $name, 'label' => 'actor'); } $rels[] = array('source' => $actors[$name], 'target' => $target); } } return json_encode(array( 'nodes' => $nodes, 'links' => $rels, )); }); If you notice, there's a cypher query which stores the results in a result array. Now, if we were to query a graph database and store the results in a PageArray, everything from there could be done processwire way (with access to processwire APIs). Graph Database seems like a natural fit to me for PW. Whether it's worth it or not is up for debate. Maybe there's performance improvements, maybe more flexibility or maybe just an alternative to mysql - i dunno. I pointed out a use case in my earlier post where graph db could be more useful, but I'm not sure - hence the discussion. Thoughts?1 point