{ "info": { "author": "Guido A.J. Stevens", "author_email": "guido.stevens@cosent.net", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Plone", "Framework :: Plone :: 5.0", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7" ], "description": ".. This README is meant for consumption by humans and pypi. Pypi can render rst files so please do not use Sphinx features.\n If you want to learn more about writing documentation, please check out: http://docs.plone.org/about/documentation_styleguide.html\n This text does not appear on pypi or github. It is a comment.\n\n===================\ncollective.mustread\n===================\n\nTrack reads on content objects in Plone.\n\nFeatures\n========\n\n- Mark objects as must-read\n\n- Keep a record of first reads of content objects per user\n\n- Query if a specific user has read a specific content object\n\n- List top-x of content objects by user reads in a specific time window\n\n\nLimitations\n-----------\n\nThis is not a install-and-forget plugin for Plone.\n\nThis product *does not track reads out of the box*.\nIt merely provides a backend you can use for doing so.\n\nDevelopment of this backend was sponsored by Quaive.\nQuaive has it's own frontend integration on top of this backend to cater for the specific use cases Quaive needs. We hope that this generic backend is useful for other Plone projects as well.\n\nRationale\n---------\n\nIf you'd want a naive implementation to track reads, you could simply\ncreate a behavior that stores a list of user ids on every content object.\n\nObviously that would soon destroy your site with database writes.\n\nInstead, this backend is designed to:\n\n- Be compatible with async scheduling, even if it does not provide async itself.\n\n- Be flexible to support multiple policy scenarios, without having to rewrite or fork the whole backend.\n\n- Use a pluggable SQL backend instead of the ZODB, both to offload writes and to make it easier to run reporting queries.\n\nArchitecture\n============\n\nYou're forgiven for thinking the architecture below is overly complex.\nPlease see the rationale above.\n\nNot included in ``collective.mustread`` is the frontend and async part::\n\n [ user browser ] -> [ view ] -> [ async queue ]\n\nThe backend implementation in this package provides the following::\n\n [ @@mustread-hit ] -> [behavior] -> [database store]\n\nLet's narrate that starting at the database end.\n\nDatabase\n--------\n\nThe database storage provides a rich API as specified in ``collective.mustread.interfaces.ITracker``.\n\nBy default collective.mustread writes to an in-memory sqlite database.\nData will be lost on zope-server restarts.\n\nTo persist your data you can use a sqlite-database-file.\n\n* Either call the `@@init-mustread-db` view (to create a sqlite db located in BUILDOUT/var/mustread.db)\n\n* or set up your database path manually in the registry and call the `@@init-mustread-db` view after that\n ( e.g. to share it with other addons - see `Auditlog compatibility`_)\n\n\nAuditlog compatibility\n''''''''''''''''''''''\n\nIf you're running ``collective.auditlog`` on your site, you might consider using the same database (so you only need one active database-connector)\n\nThe SQL store is derived from the ``collective.auditlog`` implementation.\nWe've designed ``collective.mustread`` to be compatible with ``collective.auditlog`` to the point where we'll even re-use the database connector from auditlog if possible.\n\nThe database connection is configured via a registry record ``collective.mustread.interfaces.IMustReadSettings``. You typically want this to contain the same value as your auditlog configuration.\n\nMake sure to call `@@init-mustread-db` to create the necessary tables/columns needed by this package in the database.\n\n\nBehaviors\n---------\n\nWe provide two behaviors:\n\n- ``IMaybeMustRead`` basically only provides a checkbox where you can specify whether a content object is 'must-read'.\n\n- ``ITrackReadEnabled`` activates view tracking on a content object. We track views even if ``IMaybeMustRead`` does not mark the object as 'must-read'. The reason for this is we'd like to track popular content even if the items are not compulsory.\n\nYou'd typically activate both these behaviors on the content types you'd like to track.\n\nThese behaviors are not activated by default - the ``:default`` install profile only provides a browser layer and configures the database connector. It's up to you to choose and implement your tracking policy in your own projects.\n\nThe behaviors provide a flex point where you can implement different tracking policies. You could create a behavior that only tracks reads for certain groups of users for example. You can easily do that by creating a new behavior in a few lines of code, with some extra business logic, which then re-uses our extensive read tracking API for the heavy lifting.\n\nView\n----\n\nA helper view ``@@mustread-hit`` is available for all ``ITrackReadEnabledMarker`` i.e. all objects with the ``ITrackReadEnabled`` behavior activated. Hitting that view will store a read record in the database for the content object.\n\nIn Quaive we will hit this view from our async stack.\n\nYou could conceivably, instead of this view, provide a viewlet that accesses the tracking behavior and API. Just be aware that doing all of that full sync is a risk. YMMV.\n\nThere's also a special debugging view ``@@mustread-hasread`` which will tell you whether the user you're logged in as, has read the object you're calling this view on.\n\n\nInstallation\n============\n\nInstall collective.mustread by adding it to your buildout::\n\n [buildout]\n\n ...\n\n eggs =\n collective.mustread\n\n\nand then running ``bin/buildout``\n\nOr use the built-in buildout::\n\n virtualenv .\n bin/pip install -r requirements.txt\n bin/buildout bootstrap\n bin/buildout\n\nUsing collective.mustread\n-------------------------\n\nThe minimal steps required to actually use ``collective.mustread`` in your own project:\n\n1. Install ``collective.mustread`` and configure a database connector. The default connector is a in-memory database which is not suitable for production.\n\n2. Activate the ``IMaybeMustRead`` and ``ITrackReadEnabled`` behaviors on the content types you'd like to track, via GenericSetup. Or roll your own custom behaviors.\n\n3. For these content types, hit ``${context/absolute_url}/@@mustread-hit`` when viewing the content. Ideally you'll use some kind of async queue at this stage.\n\n4. Use the tracker API to query the database and adjust your own browser views based on your own business logic. The recommended way to obtain the tracker is::\n\n from collective.mustread.interfaces import ITracker\n from zope.component import getUtility\n\n tracker = getUtility(ITracker)\n\n\nContribute\n==========\n\n- Issue Tracker: https://github.com/collective/collective.mustread/issues\n- Source Code: https://github.com/collective/collective.mustread\n\n\nSupport\n=======\n\nIf you are having issues, please let us know via the issue tracker.\n\nLicense\n=======\n\nThe project is licensed under the GPLv2.\n\n\nContributors\n============\n\n- Guido A.J. Stevens, guido.stevens@cosent.net\n\n- Harald Friessnegger, harald@webmeisterei.com\n\nChangelog\n=========\n\n\n1.1.1 (2019-03-25)\n------------------\n\n- Do not break on the upgrade step that adds columns to the mustread table\n [ale-rt]\n\n\n1.1.0 (2017-05-11)\n------------------\n\n- Added the possibility to specify engine parameters through the registry\n [ale-rt]\n\n- remove unneeded columns in ORM model (site_name, title, info) [fRiSi]\n\n- Implemented API for scheduling items as must-read for certain users.\n (see collective.contentrules.mustread for usage)\n\n This required new database columns. The provided upgrade step works for sqlite databases\n but might need changes for mysql or postgres. [fRiSi]\n\n- Allow to create and configure a database file by using the `@@init-mustread-db` view\n [fRiSI]\n\n\n1.0.1 (2016-12-28)\n------------------\n\n- Provide verbose error logging when database is not accessible [gyst]\n\n- Trivial testing change [gyst]\n\n\n\n1.0 (2016-11-24)\n----------------\n\n- Initial release.\n [gyst]", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://pypi.python.org/pypi/collective.mustread", "keywords": "Python Plone", "license": "GPL version 2", "maintainer": "", "maintainer_email": "", "name": "collective.mustread", "package_url": "https://pypi.org/project/collective.mustread/", "platform": "", "project_url": "https://pypi.org/project/collective.mustread/", "project_urls": { "Homepage": "https://pypi.python.org/pypi/collective.mustread" }, "release_url": "https://pypi.org/project/collective.mustread/1.1.1/", "requires_dist": null, "requires_python": "", "summary": "Tracking user views on content items marked as must-read", "version": "1.1.1" }, "last_serial": 4981204, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "2fbdf7d047a6be4bf15e9cc316b95ab9", "sha256": "f6fd9f42332e0853693cc49688b254545d474100b37432bdc57191fd30ffe59d" }, "downloads": -1, "filename": "collective.mustread-1.0.tar.gz", "has_sig": false, "md5_digest": "2fbdf7d047a6be4bf15e9cc316b95ab9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23666, "upload_time": "2016-11-24T14:06:03", "url": "https://files.pythonhosted.org/packages/7d/3e/9c053c6d9b6ae1947812ca8dd9b9412f6b725855da8accf7f753c105b5c6/collective.mustread-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "43b23185f47cfcf8e4d102ab650589c6", "sha256": "35fb7ac29013984d16e248dc8bcd445867be01f7c33bd4a0e8f2e458204f541f" }, "downloads": -1, "filename": "collective.mustread-1.0.1.tar.gz", "has_sig": false, "md5_digest": "43b23185f47cfcf8e4d102ab650589c6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23911, "upload_time": "2016-12-28T14:00:55", "url": "https://files.pythonhosted.org/packages/e7/50/a4a416ae593fb3b271b83ae423d25950854aac3bd78a71160499febea69a/collective.mustread-1.0.1.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "46679d6a38318e62ab7c4f5b31421b0e", "sha256": "b98f501c169d873e264243862cbb0db02bde4ad7339297f717694a7d1118786f" }, "downloads": -1, "filename": "collective.mustread-1.1.0.tar.gz", "has_sig": false, "md5_digest": "46679d6a38318e62ab7c4f5b31421b0e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30370, "upload_time": "2017-05-11T10:17:14", "url": "https://files.pythonhosted.org/packages/60/e7/d208c6b8f146cc4cccbc74db87c8e53431cfdd8990ef882b3c8650b37e56/collective.mustread-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "835e78d3d7630a5736bfff9e7c30af5a", "sha256": "2a5fdd243d6ca4507d5db90028b1d19ea151b7d582b50b0a374aeb162d1ce7cb" }, "downloads": -1, "filename": "collective.mustread-1.1.1.tar.gz", "has_sig": false, "md5_digest": "835e78d3d7630a5736bfff9e7c30af5a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35544, "upload_time": "2019-03-25T07:48:33", "url": "https://files.pythonhosted.org/packages/1b/10/bf06d6caea0b5b02d42b0a990811c3765958b9e44faf9515b284f1a3055a/collective.mustread-1.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "835e78d3d7630a5736bfff9e7c30af5a", "sha256": "2a5fdd243d6ca4507d5db90028b1d19ea151b7d582b50b0a374aeb162d1ce7cb" }, "downloads": -1, "filename": "collective.mustread-1.1.1.tar.gz", "has_sig": false, "md5_digest": "835e78d3d7630a5736bfff9e7c30af5a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35544, "upload_time": "2019-03-25T07:48:33", "url": "https://files.pythonhosted.org/packages/1b/10/bf06d6caea0b5b02d42b0a990811c3765958b9e44faf9515b284f1a3055a/collective.mustread-1.1.1.tar.gz" } ] }